From 53fdea9604fa1560bdbf418bbca564dbbebef211 Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Fri, 3 May 2019 10:48:17 +0800 Subject: [PATCH 001/626] ASoC: Intel: boards: kbl_da7219_max98927: add dai_trigger function amplifier feedback is not modeled as being dependent on any active output. Even when there is no playback happening, parts of the graph, specifically the IV sense->speaker protection->output remains active and this prevents the DSP from entering low-power states. This patch suggest a machine driver level approach where the speaker pins are enabled/disabled dynamically depending on stream start/stop events. DPAM graph representations show the feedback loop is indeed disabled and low-power states can be reached. Signed-off-by: Jenny TC Signed-off-by: Harshapriya.n Signed-off-by: Mac Chiang Acked-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_da7219_max98927.c | 73 +++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index f72a7bf028d7..1efe7fdad2cb 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -219,8 +219,60 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, return 0; } +static int kabylake_ssp0_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int j, ret; + + for (j = 0; j < rtd->num_codecs; j++) { + struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; + const char *name = codec_dai->component->name; + struct snd_soc_component *component = codec_dai->component; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char pin_name[20]; + + if (strcmp(name, MAX98927_DEV0_NAME) && + strcmp(name, MAX98927_DEV1_NAME) && + strcmp(name, MAX98373_DEV0_NAME) && + strcmp(name, MAX98373_DEV1_NAME)) + continue; + + snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk", + codec_dai->component->name_prefix); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = snd_soc_dapm_enable_pin(dapm, pin_name); + if (ret) { + dev_err(rtd->dev, "failed to enable %s: %d\n", + pin_name, ret); + return ret; + } + snd_soc_dapm_sync(dapm); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = snd_soc_dapm_disable_pin(dapm, pin_name); + if (ret) { + dev_err(rtd->dev, "failed to disable %s: %d\n", + pin_name, ret); + return ret; + } + snd_soc_dapm_sync(dapm); + break; + } + } + + return 0; +} + static struct snd_soc_ops kabylake_ssp0_ops = { .hw_params = kabylake_ssp0_hw_params, + .trigger = kabylake_ssp0_trigger, }; static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, @@ -950,6 +1002,7 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); struct kbl_hdmi_pcm *pcm; + struct snd_soc_dapm_context *dapm = &card->dapm; struct snd_soc_component *component = NULL; int err, i = 0; char jack_name[NAME_SIZE]; @@ -976,9 +1029,25 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) if (!component) return -EINVAL; - return hdac_hdmi_jack_port_init(component, &card->dapm); - return 0; + err = hdac_hdmi_jack_port_init(component, &card->dapm); + + if (err < 0) + return err; + + err = snd_soc_dapm_disable_pin(dapm, "Left Spk"); + if (err) { + dev_err(card->dev, "failed to disable Left Spk: %d\n", err); + return err; + } + + err = snd_soc_dapm_disable_pin(dapm, "Right Spk"); + if (err) { + dev_err(card->dev, "failed to disable Right Spk: %d\n", err); + return err; + } + + return snd_soc_dapm_sync(dapm); } /* kabylake audio machine driver for SPT + DA7219 */ From b9960f6ea22da072c2fb27305a1a51517c3643fe Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Fri, 3 May 2019 12:33:42 -0700 Subject: [PATCH 002/626] ASoC: rt5677-spi: Rename driver to differentiate from main codec Currently the SPI driver and the main codec share the same name. This will become confusing when looking up components when using both drivers. Signed-off-by: Curtis Malainey Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677-spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index 167a02773a0b..1efc37ee625f 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c @@ -29,6 +29,8 @@ #include "rt5677-spi.h" +#define DRV_NAME "rt5677spi" + #define RT5677_SPI_BURST_LEN 240 #define RT5677_SPI_HEADER 5 #define RT5677_SPI_FREQ 6000000 @@ -235,7 +237,7 @@ MODULE_DEVICE_TABLE(acpi, rt5677_spi_acpi_id); static struct spi_driver rt5677_spi_driver = { .driver = { - .name = "rt5677", + .name = DRV_NAME, .acpi_match_table = ACPI_PTR(rt5677_spi_acpi_id), }, .probe = rt5677_spi_probe, From 1a5c0b28fc56044737f988960f3bc5fdcdba0827 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 6 May 2019 14:44:06 +0200 Subject: [PATCH 003/626] ASoC: stm32: spdifrx: manage identification registers Add support of identification registers in STM32 SPDIFRX. Signed-off-by: Olivier Moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_spdifrx.c | 37 +++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index b4c3d983e195..62a887ee4a03 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -16,6 +16,7 @@ * details. */ +#include #include #include #include @@ -36,6 +37,9 @@ #define STM32_SPDIFRX_DR 0x10 #define STM32_SPDIFRX_CSR 0x14 #define STM32_SPDIFRX_DIR 0x18 +#define STM32_SPDIFRX_VERR 0x3F4 +#define STM32_SPDIFRX_IDR 0x3F8 +#define STM32_SPDIFRX_SIDR 0x3FC /* Bit definition for SPDIF_CR register */ #define SPDIFRX_CR_SPDIFEN_SHIFT 0 @@ -169,6 +173,18 @@ #define SPDIFRX_SPDIFEN_SYNC 0x1 #define SPDIFRX_SPDIFEN_ENABLE 0x3 +/* Bit definition for SPDIFRX_VERR register */ +#define SPDIFRX_VERR_MIN_MASK GENMASK(3, 0) +#define SPDIFRX_VERR_MAJ_MASK GENMASK(7, 4) + +/* Bit definition for SPDIFRX_IDR register */ +#define SPDIFRX_IDR_ID_MASK GENMASK(31, 0) + +/* Bit definition for SPDIFRX_SIDR register */ +#define SPDIFRX_SIDR_SID_MASK GENMASK(31, 0) + +#define SPDIFRX_IPIDR_NUMBER 0x00130041 + #define SPDIFRX_IN1 0x1 #define SPDIFRX_IN2 0x2 #define SPDIFRX_IN3 0x3 @@ -607,6 +623,9 @@ static bool stm32_spdifrx_readable_reg(struct device *dev, unsigned int reg) case STM32_SPDIFRX_DR: case STM32_SPDIFRX_CSR: case STM32_SPDIFRX_DIR: + case STM32_SPDIFRX_VERR: + case STM32_SPDIFRX_IDR: + case STM32_SPDIFRX_SIDR: return true; default: return false; @@ -642,10 +661,11 @@ static const struct regmap_config stm32_h7_spdifrx_regmap_conf = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = STM32_SPDIFRX_DIR, + .max_register = STM32_SPDIFRX_SIDR, .readable_reg = stm32_spdifrx_readable_reg, .volatile_reg = stm32_spdifrx_volatile_reg, .writeable_reg = stm32_spdifrx_writeable_reg, + .num_reg_defaults_raw = STM32_SPDIFRX_SIDR / sizeof(u32) + 1, .fast_io = true, .cache_type = REGCACHE_FLAT, }; @@ -911,6 +931,7 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) struct stm32_spdifrx_data *spdifrx; struct reset_control *rst; const struct snd_dmaengine_pcm_config *pcm_config = NULL; + u32 ver, idr; int ret; spdifrx = devm_kzalloc(&pdev->dev, sizeof(*spdifrx), GFP_KERNEL); @@ -967,7 +988,19 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) goto error; } - return 0; + ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_IDR, &idr); + if (ret) + goto error; + + if (idr == SPDIFRX_IPIDR_NUMBER) { + ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_VERR, &ver); + + dev_dbg(&pdev->dev, "SPDIFRX version: %lu.%lu registered\n", + FIELD_GET(SPDIFRX_VERR_MAJ_MASK, ver), + FIELD_GET(SPDIFRX_VERR_MIN_MASK, ver)); + } + + return ret; error: if (!IS_ERR(spdifrx->ctrl_chan)) From b2d337d8de9fb6dd4f2970ebec0fa2375f7c9cdd Mon Sep 17 00:00:00 2001 From: "S.j. Wang" Date: Fri, 3 May 2019 12:49:44 -0700 Subject: [PATCH 004/626] ASoC: fsl_esai: Add pm runtime function Add pm runtime support and move clock handling there. Close the clocks at suspend to reduce the power consumption. fsl_esai_suspend is replaced by pm_runtime_force_suspend. fsl_esai_resume is replaced by pm_runtime_force_resume. Signed-off-by: Shengjiu Wang Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 141 +++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 64 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index bad0dfed6b68..10d2210c91ef 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -466,30 +467,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); - int ret; - - /* - * Some platforms might use the same bit to gate all three or two of - * clocks, so keep all clocks open/close at the same time for safety - */ - ret = clk_prepare_enable(esai_priv->coreclk); - if (ret) - return ret; - if (!IS_ERR(esai_priv->spbaclk)) { - ret = clk_prepare_enable(esai_priv->spbaclk); - if (ret) - goto err_spbaclk; - } - if (!IS_ERR(esai_priv->extalclk)) { - ret = clk_prepare_enable(esai_priv->extalclk); - if (ret) - goto err_extalck; - } - if (!IS_ERR(esai_priv->fsysclk)) { - ret = clk_prepare_enable(esai_priv->fsysclk); - if (ret) - goto err_fsysclk; - } if (!dai->active) { /* Set synchronous mode */ @@ -506,16 +483,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, return 0; -err_fsysclk: - if (!IS_ERR(esai_priv->extalclk)) - clk_disable_unprepare(esai_priv->extalclk); -err_extalck: - if (!IS_ERR(esai_priv->spbaclk)) - clk_disable_unprepare(esai_priv->spbaclk); -err_spbaclk: - clk_disable_unprepare(esai_priv->coreclk); - - return ret; } static int fsl_esai_hw_params(struct snd_pcm_substream *substream, @@ -576,20 +543,6 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, return 0; } -static void fsl_esai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); - - if (!IS_ERR(esai_priv->fsysclk)) - clk_disable_unprepare(esai_priv->fsysclk); - if (!IS_ERR(esai_priv->extalclk)) - clk_disable_unprepare(esai_priv->extalclk); - if (!IS_ERR(esai_priv->spbaclk)) - clk_disable_unprepare(esai_priv->spbaclk); - clk_disable_unprepare(esai_priv->coreclk); -} - static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -658,7 +611,6 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, static const struct snd_soc_dai_ops fsl_esai_dai_ops = { .startup = fsl_esai_startup, - .shutdown = fsl_esai_shutdown, .trigger = fsl_esai_trigger, .hw_params = fsl_esai_hw_params, .set_sysclk = fsl_esai_set_dai_sysclk, @@ -947,6 +899,10 @@ static int fsl_esai_probe(struct platform_device *pdev) return ret; } + pm_runtime_enable(&pdev->dev); + + regcache_cache_only(esai_priv->regmap, true); + ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE); if (ret) dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); @@ -954,6 +910,13 @@ static int fsl_esai_probe(struct platform_device *pdev) return ret; } +static int fsl_esai_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + static const struct of_device_id fsl_esai_dt_ids[] = { { .compatible = "fsl,imx35-esai", }, { .compatible = "fsl,vf610-esai", }, @@ -961,22 +924,35 @@ static const struct of_device_id fsl_esai_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); -#ifdef CONFIG_PM_SLEEP -static int fsl_esai_suspend(struct device *dev) -{ - struct fsl_esai *esai = dev_get_drvdata(dev); - - regcache_cache_only(esai->regmap, true); - regcache_mark_dirty(esai->regmap); - - return 0; -} - -static int fsl_esai_resume(struct device *dev) +#ifdef CONFIG_PM +static int fsl_esai_runtime_resume(struct device *dev) { struct fsl_esai *esai = dev_get_drvdata(dev); int ret; + /* + * Some platforms might use the same bit to gate all three or two of + * clocks, so keep all clocks open/close at the same time for safety + */ + ret = clk_prepare_enable(esai->coreclk); + if (ret) + return ret; + if (!IS_ERR(esai->spbaclk)) { + ret = clk_prepare_enable(esai->spbaclk); + if (ret) + goto err_spbaclk; + } + if (!IS_ERR(esai->extalclk)) { + ret = clk_prepare_enable(esai->extalclk); + if (ret) + goto err_extalclk; + } + if (!IS_ERR(esai->fsysclk)) { + ret = clk_prepare_enable(esai->fsysclk); + if (ret) + goto err_fsysclk; + } + regcache_cache_only(esai->regmap, false); /* FIFO reset for safety */ @@ -987,22 +963,59 @@ static int fsl_esai_resume(struct device *dev) ret = regcache_sync(esai->regmap); if (ret) - return ret; + goto err_regcache_sync; /* FIFO reset done */ regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); return 0; + +err_regcache_sync: + if (!IS_ERR(esai->fsysclk)) + clk_disable_unprepare(esai->fsysclk); +err_fsysclk: + if (!IS_ERR(esai->extalclk)) + clk_disable_unprepare(esai->extalclk); +err_extalclk: + if (!IS_ERR(esai->spbaclk)) + clk_disable_unprepare(esai->spbaclk); +err_spbaclk: + clk_disable_unprepare(esai->coreclk); + + return ret; } -#endif /* CONFIG_PM_SLEEP */ + +static int fsl_esai_runtime_suspend(struct device *dev) +{ + struct fsl_esai *esai = dev_get_drvdata(dev); + + regcache_cache_only(esai->regmap, true); + regcache_mark_dirty(esai->regmap); + + if (!IS_ERR(esai->fsysclk)) + clk_disable_unprepare(esai->fsysclk); + if (!IS_ERR(esai->extalclk)) + clk_disable_unprepare(esai->extalclk); + if (!IS_ERR(esai->spbaclk)) + clk_disable_unprepare(esai->spbaclk); + clk_disable_unprepare(esai->coreclk); + + return 0; +} +#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_esai_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fsl_esai_suspend, fsl_esai_resume) + SET_RUNTIME_PM_OPS(fsl_esai_runtime_suspend, + fsl_esai_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static struct platform_driver fsl_esai_driver = { .probe = fsl_esai_probe, + .remove = fsl_esai_remove, .driver = { .name = "fsl-esai-dai", .pm = &fsl_esai_pm_ops, From 753c36a4d8a85beeb97640d1f91f2ead6aaee85e Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Mon, 6 May 2019 13:30:06 -0700 Subject: [PATCH 005/626] ASoC: rt5677: use more of the volume range from DACs The DACs volume can go over 0, both according to the data sheet and real world testing. The control can go up to +30dB. This was tested by playing audio at full volume on a samus chromebook. Signed-off-by: Dylan Reid Reviewed-by: Hsinyu Chao Signed-off-by: Ross Zwisler Signed-off-by: Curtis Malainey Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 6fc70e441458..907c957b614d 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -832,13 +832,13 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = { /* DAC Digital Volume */ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5677_DAC1_DIG_VOL, - RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv), + RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 127, 0, dac_vol_tlv), SOC_DOUBLE_TLV("DAC2 Playback Volume", RT5677_DAC2_DIG_VOL, - RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv), + RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 127, 0, dac_vol_tlv), SOC_DOUBLE_TLV("DAC3 Playback Volume", RT5677_DAC3_DIG_VOL, - RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv), + RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 127, 0, dac_vol_tlv), SOC_DOUBLE_TLV("DAC4 Playback Volume", RT5677_DAC4_DIG_VOL, - RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv), + RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 127, 0, dac_vol_tlv), /* IN1/IN2 Control */ SOC_SINGLE_TLV("IN1 Boost", RT5677_IN1, RT5677_BST_SFT1, 8, 0, bst_tlv), From 893d1a9c5c1c246eb756c828a12b5966d2ed9a17 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Tue, 7 May 2019 16:32:13 -0700 Subject: [PATCH 006/626] ASoC: rt5677: Add component driver name Add name to component driver so it is possible to lookup the component when needed. Signed-off-by: Curtis Malainey Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 7 ++++--- sound/soc/codecs/rt5677.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 907c957b614d..c49b5c218666 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4650,7 +4650,7 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) } static const struct gpio_chip rt5677_template_chip = { - .label = "rt5677", + .label = RT5677_DRV_NAME, .owner = THIS_MODULE, .direction_output = rt5677_gpio_direction_out, .set = rt5677_gpio_set, @@ -4958,6 +4958,7 @@ static struct snd_soc_dai_driver rt5677_dai[] = { }; static const struct snd_soc_component_driver soc_component_dev_rt5677 = { + .name = RT5677_DRV_NAME, .probe = rt5677_probe, .remove = rt5677_remove, .suspend = rt5677_suspend, @@ -5079,7 +5080,7 @@ static struct regmap_irq rt5677_irqs[] = { }; static struct regmap_irq_chip rt5677_irq_chip = { - .name = "rt5677", + .name = RT5677_DRV_NAME, .irqs = rt5677_irqs, .num_irqs = ARRAY_SIZE(rt5677_irqs), @@ -5267,7 +5268,7 @@ static int rt5677_i2c_remove(struct i2c_client *i2c) static struct i2c_driver rt5677_i2c_driver = { .driver = { - .name = "rt5677", + .name = RT5677_DRV_NAME, .of_match_table = rt5677_of_match, .acpi_match_table = ACPI_PTR(rt5677_acpi_match), }, diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 183d92b03045..11a2ffceec3b 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h @@ -1674,6 +1674,8 @@ #define RT5677_FIRMWARE1 "rt5677_dsp_fw1.bin" #define RT5677_FIRMWARE2 "rt5677_dsp_fw2.bin" +#define RT5677_DRV_NAME "rt5677" + /* System Clock Source */ enum { RT5677_SCLK_S_MCLK, From 900e5daf7034cf65ce4072b86f297c42f9042433 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 6 May 2019 11:58:12 +0200 Subject: [PATCH 007/626] ASoC: hdmi-codec: remove function name debug traces Remove the debug traces only showing the function name on entry. The same can be obtained using ftrace. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 39caf19abb0b..eb31d7eddcbf 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -416,8 +416,6 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); int ret = 0; - dev_dbg(dai->dev, "%s()\n", __func__); - ret = hdmi_codec_new_stream(substream, dai); if (ret) return ret; @@ -457,8 +455,6 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); - dev_dbg(dai->dev, "%s()\n", __func__); - WARN_ON(hcp->current_stream != substream); hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; @@ -527,8 +523,6 @@ static int hdmi_codec_set_fmt(struct snd_soc_dai *dai, struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); struct hdmi_codec_daifmt cf = { 0 }; - dev_dbg(dai->dev, "%s()\n", __func__); - if (dai->id == DAI_ID_SPDIF) return 0; @@ -597,8 +591,6 @@ static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); - dev_dbg(dai->dev, "%s()\n", __func__); - if (hcp->hcd.ops->digital_mute) return hcp->hcd.ops->digital_mute(dai->dev->parent, hcp->hcd.data, mute); @@ -656,8 +648,6 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, }; int ret; - dev_dbg(dai->dev, "%s()\n", __func__); - ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK, NULL, drv->playback.channels_max, 0, &hcp->chmap_info); @@ -754,8 +744,6 @@ static int hdmi_codec_probe(struct platform_device *pdev) int dai_count, i = 0; int ret; - dev_dbg(dev, "%s()\n", __func__); - if (!hcd) { dev_err(dev, "%s: No platform data\n", __func__); return -EINVAL; From 3fcf94ef4d418668fa66e33ce9aabb05689b55f6 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 6 May 2019 11:58:13 +0200 Subject: [PATCH 008/626] ASoC: hdmi-codec: remove reference to the current substream If the hdmi-codec is on a codec-to-codec link, the substream pointer it receives is completely made up by snd_soc_dai_link_event(). The pointer will be different between startup() and shutdown(). The hdmi-codec complains when this happens even if it is not really a problem. The current_substream pointer is not used for anything useful apart from getting the exclusive ownership of the device. Remove current_substream pointer and replace the exclusive locking mechanism with a simple variable and some atomic operations. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 58 ++++++++++------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index eb31d7eddcbf..4d32f93f6be6 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -280,11 +280,10 @@ struct hdmi_codec_priv { struct hdmi_codec_pdata hcd; struct snd_soc_dai_driver *daidrv; struct hdmi_codec_daifmt daifmt[2]; - struct mutex current_stream_lock; - struct snd_pcm_substream *current_stream; uint8_t eld[MAX_ELD_BYTES]; struct snd_pcm_chmap *chmap_info; unsigned int chmap_idx; + unsigned long busy; }; static const struct snd_soc_dapm_widget hdmi_widgets[] = { @@ -392,42 +391,22 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol, return 0; } -static int hdmi_codec_new_stream(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); - int ret = 0; - - mutex_lock(&hcp->current_stream_lock); - if (!hcp->current_stream) { - hcp->current_stream = substream; - } else if (hcp->current_stream != substream) { - dev_err(dai->dev, "Only one simultaneous stream supported!\n"); - ret = -EINVAL; - } - mutex_unlock(&hcp->current_stream_lock); - - return ret; -} - static int hdmi_codec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); int ret = 0; - ret = hdmi_codec_new_stream(substream, dai); - if (ret) - return ret; + ret = test_and_set_bit(0, &hcp->busy); + if (ret) { + dev_err(dai->dev, "Only one simultaneous stream supported!\n"); + return -EINVAL; + } if (hcp->hcd.ops->audio_startup) { ret = hcp->hcd.ops->audio_startup(dai->dev->parent, hcp->hcd.data); - if (ret) { - mutex_lock(&hcp->current_stream_lock); - hcp->current_stream = NULL; - mutex_unlock(&hcp->current_stream_lock); - return ret; - } + if (ret) + goto err; } if (hcp->hcd.ops->get_eld) { @@ -437,17 +416,18 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, if (!ret) { ret = snd_pcm_hw_constraint_eld(substream->runtime, hcp->eld); - if (ret) { - mutex_lock(&hcp->current_stream_lock); - hcp->current_stream = NULL; - mutex_unlock(&hcp->current_stream_lock); - return ret; - } + if (ret) + goto err; } /* Select chmap supported */ hdmi_codec_eld_chmap(hcp); } return 0; + +err: + /* Release the exclusive lock on error */ + clear_bit(0, &hcp->busy); + return ret; } static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, @@ -455,14 +435,10 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); - WARN_ON(hcp->current_stream != substream); - hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); - mutex_lock(&hcp->current_stream_lock); - hcp->current_stream = NULL; - mutex_unlock(&hcp->current_stream_lock); + clear_bit(0, &hcp->busy); } static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, @@ -761,8 +737,6 @@ static int hdmi_codec_probe(struct platform_device *pdev) return -ENOMEM; hcp->hcd = *hcd; - mutex_init(&hcp->current_stream_lock); - hcp->daidrv = devm_kcalloc(dev, dai_count, sizeof(*hcp->daidrv), GFP_KERNEL); if (!hcp->daidrv) From 1de005d47d90343666c5cc50a50929e05e52baac Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 6 May 2019 11:58:14 +0200 Subject: [PATCH 009/626] ASoC: hdmi-codec: remove reference to the dai drivers in the private data Keeping the a pointer to the dai drivers is not necessary. It is not used by the hdmi_codec after the probe. Even if it was used, the 'struct snd_soc_dai_driver' can accessed through the 'struct snd_soc_dai' so keeping the pointer in the private data structure is not useful. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 4d32f93f6be6..9408e6bc4d3e 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -278,7 +278,6 @@ static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { struct hdmi_codec_priv { struct hdmi_codec_pdata hcd; - struct snd_soc_dai_driver *daidrv; struct hdmi_codec_daifmt daifmt[2]; uint8_t eld[MAX_ELD_BYTES]; struct snd_pcm_chmap *chmap_info; @@ -715,6 +714,7 @@ static const struct snd_soc_component_driver hdmi_driver = { static int hdmi_codec_probe(struct platform_device *pdev) { struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; + struct snd_soc_dai_driver *daidrv; struct device *dev = &pdev->dev; struct hdmi_codec_priv *hcp; int dai_count, i = 0; @@ -737,27 +737,25 @@ static int hdmi_codec_probe(struct platform_device *pdev) return -ENOMEM; hcp->hcd = *hcd; - hcp->daidrv = devm_kcalloc(dev, dai_count, sizeof(*hcp->daidrv), - GFP_KERNEL); - if (!hcp->daidrv) + daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL); + if (!daidrv) return -ENOMEM; if (hcd->i2s) { - hcp->daidrv[i] = hdmi_i2s_dai; - hcp->daidrv[i].playback.channels_max = - hcd->max_i2s_channels; + daidrv[i] = hdmi_i2s_dai; + daidrv[i].playback.channels_max = hcd->max_i2s_channels; i++; } if (hcd->spdif) { - hcp->daidrv[i] = hdmi_spdif_dai; + daidrv[i] = hdmi_spdif_dai; hcp->daifmt[DAI_ID_SPDIF].fmt = HDMI_SPDIF; } dev_set_drvdata(dev, hcp); - ret = devm_snd_soc_register_component(dev, &hdmi_driver, hcp->daidrv, - dai_count); + ret = devm_snd_soc_register_component(dev, &hdmi_driver, daidrv, + dai_count); if (ret) { dev_err(dev, "%s: snd_soc_register_component() failed (%d)\n", __func__, ret); From 0cf4610b9f297e570da4d98514b310f076ecc8ab Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 6 May 2019 11:58:15 +0200 Subject: [PATCH 010/626] ASoC: hdmi-codec: remove ops dependency on the dai id The dependency on the dai_id can be removed by setting different ops for the i2s and spdif dai and storing the dai format information in each dai structure. It simplies the code a bit. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 100 +++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 9408e6bc4d3e..90a892766625 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -278,7 +278,6 @@ static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { struct hdmi_codec_priv { struct hdmi_codec_pdata hcd; - struct hdmi_codec_daifmt daifmt[2]; uint8_t eld[MAX_ELD_BYTES]; struct snd_pcm_chmap *chmap_info; unsigned int chmap_idx; @@ -445,6 +444,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + struct hdmi_codec_daifmt *cf = dai->playback_dma_data; struct hdmi_codec_params hp = { .iec = { .status = { 0 }, @@ -489,28 +489,27 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, hp.channels = params_channels(params); return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data, - &hcp->daifmt[dai->id], &hp); + cf, &hp); } -static int hdmi_codec_set_fmt(struct snd_soc_dai *dai, - unsigned int fmt) +static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai, + unsigned int fmt) { - struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); - struct hdmi_codec_daifmt cf = { 0 }; + struct hdmi_codec_daifmt *cf = dai->playback_dma_data; - if (dai->id == DAI_ID_SPDIF) - return 0; + /* Reset daifmt */ + memset(cf, 0, sizeof(*cf)); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - cf.bit_clk_master = 1; - cf.frame_clk_master = 1; + cf->bit_clk_master = 1; + cf->frame_clk_master = 1; break; case SND_SOC_DAIFMT_CBS_CFM: - cf.frame_clk_master = 1; + cf->frame_clk_master = 1; break; case SND_SOC_DAIFMT_CBM_CFS: - cf.bit_clk_master = 1; + cf->bit_clk_master = 1; break; case SND_SOC_DAIFMT_CBS_CFS: break; @@ -522,43 +521,41 @@ static int hdmi_codec_set_fmt(struct snd_soc_dai *dai, case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_NB_IF: - cf.frame_clk_inv = 1; + cf->frame_clk_inv = 1; break; case SND_SOC_DAIFMT_IB_NF: - cf.bit_clk_inv = 1; + cf->bit_clk_inv = 1; break; case SND_SOC_DAIFMT_IB_IF: - cf.frame_clk_inv = 1; - cf.bit_clk_inv = 1; + cf->frame_clk_inv = 1; + cf->bit_clk_inv = 1; break; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - cf.fmt = HDMI_I2S; + cf->fmt = HDMI_I2S; break; case SND_SOC_DAIFMT_DSP_A: - cf.fmt = HDMI_DSP_A; + cf->fmt = HDMI_DSP_A; break; case SND_SOC_DAIFMT_DSP_B: - cf.fmt = HDMI_DSP_B; + cf->fmt = HDMI_DSP_B; break; case SND_SOC_DAIFMT_RIGHT_J: - cf.fmt = HDMI_RIGHT_J; + cf->fmt = HDMI_RIGHT_J; break; case SND_SOC_DAIFMT_LEFT_J: - cf.fmt = HDMI_LEFT_J; + cf->fmt = HDMI_LEFT_J; break; case SND_SOC_DAIFMT_AC97: - cf.fmt = HDMI_AC97; + cf->fmt = HDMI_AC97; break; default: dev_err(dai->dev, "Invalid DAI interface format\n"); return -EINVAL; } - hcp->daifmt[dai->id] = cf; - return 0; } @@ -573,14 +570,20 @@ static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) return 0; } -static const struct snd_soc_dai_ops hdmi_dai_ops = { +static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = { .startup = hdmi_codec_startup, .shutdown = hdmi_codec_shutdown, .hw_params = hdmi_codec_hw_params, - .set_fmt = hdmi_codec_set_fmt, + .set_fmt = hdmi_codec_i2s_set_fmt, .digital_mute = hdmi_codec_digital_mute, }; +static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = { + .startup = hdmi_codec_startup, + .shutdown = hdmi_codec_shutdown, + .hw_params = hdmi_codec_hw_params, + .digital_mute = hdmi_codec_digital_mute, +}; #define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ @@ -648,20 +651,52 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, static int hdmi_dai_probe(struct snd_soc_dai *dai) { struct snd_soc_dapm_context *dapm; + struct hdmi_codec_daifmt *daifmt; struct snd_soc_dapm_route route = { .sink = "TX", .source = dai->driver->playback.stream_name, }; + int ret; dapm = snd_soc_component_get_dapm(dai->component); + ret = snd_soc_dapm_add_routes(dapm, &route, 1); + if (ret) + return ret; - return snd_soc_dapm_add_routes(dapm, &route, 1); + daifmt = kzalloc(sizeof(*daifmt), GFP_KERNEL); + if (!daifmt) + return -ENOMEM; + + dai->playback_dma_data = daifmt; + return 0; +} + +static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai) +{ + struct hdmi_codec_daifmt *cf = dai->playback_dma_data; + int ret; + + ret = hdmi_dai_probe(dai); + if (ret) + return ret; + + cf = dai->playback_dma_data; + cf->fmt = HDMI_SPDIF; + + return 0; +} + +static int hdmi_codec_dai_remove(struct snd_soc_dai *dai) +{ + kfree(dai->playback_dma_data); + return 0; } static const struct snd_soc_dai_driver hdmi_i2s_dai = { .name = "i2s-hifi", .id = DAI_ID_I2S, .probe = hdmi_dai_probe, + .remove = hdmi_codec_dai_remove, .playback = { .stream_name = "I2S Playback", .channels_min = 2, @@ -670,14 +705,15 @@ static const struct snd_soc_dai_driver hdmi_i2s_dai = { .formats = I2S_FORMATS, .sig_bits = 24, }, - .ops = &hdmi_dai_ops, + .ops = &hdmi_codec_i2s_dai_ops, .pcm_new = hdmi_codec_pcm_new, }; static const struct snd_soc_dai_driver hdmi_spdif_dai = { .name = "spdif-hifi", .id = DAI_ID_SPDIF, - .probe = hdmi_dai_probe, + .probe = hdmi_dai_spdif_probe, + .remove = hdmi_codec_dai_remove, .playback = { .stream_name = "SPDIF Playback", .channels_min = 2, @@ -685,7 +721,7 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { .rates = HDMI_RATES, .formats = SPDIF_FORMATS, }, - .ops = &hdmi_dai_ops, + .ops = &hdmi_codec_spdif_dai_ops, .pcm_new = hdmi_codec_pcm_new, }; @@ -747,10 +783,8 @@ static int hdmi_codec_probe(struct platform_device *pdev) i++; } - if (hcd->spdif) { + if (hcd->spdif) daidrv[i] = hdmi_spdif_dai; - hcp->daifmt[DAI_ID_SPDIF].fmt = HDMI_SPDIF; - } dev_set_drvdata(dev, hcp); From 71ed4bddde08285cd02d6d28c861ea1815d67476 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 6 May 2019 14:54:12 +0200 Subject: [PATCH 011/626] ASoC: stm32: i2s: manage identification registers Add support of identification registers in STM32 I2S. Signed-off-by: Olivier Moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 60 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 97d5e9901a0e..9755c49ae7dc 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -16,6 +16,7 @@ * details. */ +#include #include #include #include @@ -37,6 +38,10 @@ #define STM32_I2S_TXDR_REG 0X20 #define STM32_I2S_RXDR_REG 0x30 #define STM32_I2S_CGFR_REG 0X50 +#define STM32_I2S_HWCFGR_REG 0x3F0 +#define STM32_I2S_VERR_REG 0x3F4 +#define STM32_I2S_IPIDR_REG 0x3F8 +#define STM32_I2S_SIDR_REG 0x3FC /* Bit definition for SPI2S_CR1 register */ #define I2S_CR1_SPE BIT(0) @@ -143,6 +148,23 @@ #define I2S_CGFR_ODD BIT(I2S_CGFR_ODD_SHIFT) #define I2S_CGFR_MCKOE BIT(25) +/* Registers below apply to I2S version 1.1 and more */ + +/* Bit definition for SPI_HWCFGR register */ +#define I2S_HWCFGR_I2S_SUPPORT_MASK GENMASK(15, 12) + +/* Bit definition for SPI_VERR register */ +#define I2S_VERR_MIN_MASK GENMASK(3, 0) +#define I2S_VERR_MAJ_MASK GENMASK(7, 4) + +/* Bit definition for SPI_IPIDR register */ +#define I2S_IPIDR_ID_MASK GENMASK(31, 0) + +/* Bit definition for SPI_SIDR register */ +#define I2S_SIDR_ID_MASK GENMASK(31, 0) + +#define I2S_IPIDR_NUMBER 0x00130022 + enum i2s_master_mode { I2S_MS_NOT_SET, I2S_MS_MASTER, @@ -280,6 +302,10 @@ static bool stm32_i2s_readable_reg(struct device *dev, unsigned int reg) case STM32_I2S_SR_REG: case STM32_I2S_RXDR_REG: case STM32_I2S_CGFR_REG: + case STM32_I2S_HWCFGR_REG: + case STM32_I2S_VERR_REG: + case STM32_I2S_IPIDR_REG: + case STM32_I2S_SIDR_REG: return true; default: return false; @@ -711,10 +737,11 @@ static const struct regmap_config stm32_h7_i2s_regmap_conf = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = STM32_I2S_CGFR_REG, + .max_register = STM32_I2S_SIDR_REG, .readable_reg = stm32_i2s_readable_reg, .volatile_reg = stm32_i2s_volatile_reg, .writeable_reg = stm32_i2s_writeable_reg, + .num_reg_defaults_raw = STM32_I2S_SIDR_REG / sizeof(u32) + 1, .fast_io = true, .cache_type = REGCACHE_FLAT, }; @@ -864,6 +891,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, static int stm32_i2s_probe(struct platform_device *pdev) { struct stm32_i2s_data *i2s; + u32 val; int ret; i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); @@ -902,8 +930,34 @@ static int stm32_i2s_probe(struct platform_device *pdev) return ret; /* Set SPI/I2S in i2s mode */ - return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, - I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD); + ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, + I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD); + if (ret) + return ret; + + ret = regmap_read(i2s->regmap, STM32_I2S_IPIDR_REG, &val); + if (ret) + return ret; + + if (val == I2S_IPIDR_NUMBER) { + ret = regmap_read(i2s->regmap, STM32_I2S_HWCFGR_REG, &val); + if (ret) + return ret; + + if (!FIELD_GET(I2S_HWCFGR_I2S_SUPPORT_MASK, val)) { + dev_err(&pdev->dev, + "Device does not support i2s mode\n"); + return -EPERM; + } + + ret = regmap_read(i2s->regmap, STM32_I2S_VERR_REG, &val); + + dev_dbg(&pdev->dev, "I2S version: %lu.%lu registered\n", + FIELD_GET(I2S_VERR_MAJ_MASK, val), + FIELD_GET(I2S_VERR_MIN_MASK, val)); + } + + return ret; } MODULE_DEVICE_TABLE(of, stm32_i2s_ids); From c0ffbd64b9dc14d673e393cc5933f3b4a47ab39c Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Tue, 7 May 2019 14:06:52 +0000 Subject: [PATCH 012/626] ASoC: fsl_sai: Move clock operation to PM runtime Turn off/on clocks when device enters suspend/resume. This can help saving power. As a further optimization, we turn off/on mclk only when SAI is in master mode because otherwise mclk is externally provided. Signed-off-by: Shengjiu Wang Signed-off-by: Daniel Baluta Reviewed-by: Viorel Suman Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 54 +++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 8593269156bd..d58cc3ae90d8 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -596,15 +596,8 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct device *dev = &sai->pdev->dev; int ret; - ret = clk_prepare_enable(sai->bus_clk); - if (ret) { - dev_err(dev, "failed to enable bus clock: %d\n", ret); - return ret; - } - regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, FSL_SAI_CR3_TRCE); @@ -621,8 +614,6 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream, bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0); - - clk_disable_unprepare(sai->bus_clk); } static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { @@ -935,6 +926,14 @@ static int fsl_sai_runtime_suspend(struct device *dev) { struct fsl_sai *sai = dev_get_drvdata(dev); + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) + clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]); + + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) + clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]); + + clk_disable_unprepare(sai->bus_clk); + regcache_cache_only(sai->regmap, true); regcache_mark_dirty(sai->regmap); @@ -944,6 +943,25 @@ static int fsl_sai_runtime_suspend(struct device *dev) static int fsl_sai_runtime_resume(struct device *dev) { struct fsl_sai *sai = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(sai->bus_clk); + if (ret) { + dev_err(dev, "failed to enable bus clock: %d\n", ret); + return ret; + } + + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) { + ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]); + if (ret) + goto disable_bus_clk; + } + + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) { + ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]); + if (ret) + goto disable_tx_clk; + } regcache_cache_only(sai->regmap, false); regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); @@ -951,7 +969,23 @@ static int fsl_sai_runtime_resume(struct device *dev) usleep_range(1000, 2000); regmap_write(sai->regmap, FSL_SAI_TCSR, 0); regmap_write(sai->regmap, FSL_SAI_RCSR, 0); - return regcache_sync(sai->regmap); + + ret = regcache_sync(sai->regmap); + if (ret) + goto disable_rx_clk; + + return 0; + +disable_rx_clk: + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) + clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]); +disable_tx_clk: + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) + clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]); +disable_bus_clk: + clk_disable_unprepare(sai->bus_clk); + + return ret; } #endif /* CONFIG_PM */ From 261e90829fe2f0ab8a9e3912da1126abd3224ad7 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sat, 13 Apr 2019 11:15:18 -0400 Subject: [PATCH 013/626] ASoC: soc-acpi: fix implicit header use of module.h/export.h This file is implicitly relying on an instance of including module.h from . Ideally, header files under include/linux shouldn't be adding includes of other headers, in anticipation of their consumers, but just the headers needed for the header itself to pass parsing with CPP. The module.h is particularly bad in this sense, as it itself does include a whole bunch of other headers, due to the complexity of module support. Here, we make the include explicit, in order to allow the future removal of module.h from linux/acpi.h without causing build breakage. Cc: Liam Girdwood Cc: Mark Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Signed-off-by: Paul Gortmaker Signed-off-by: Mark Brown --- sound/soc/soc-acpi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-acpi.c b/sound/soc/soc-acpi.c index 4fb29f0e561e..444ce0602f76 100644 --- a/sound/soc/soc-acpi.c +++ b/sound/soc/soc-acpi.c @@ -4,6 +4,8 @@ // // Copyright (c) 2013-15, Intel Corporation. +#include +#include #include struct snd_soc_acpi_mach * From 35a7086eaa057a5ef6eef77af957e46c040be48b Mon Sep 17 00:00:00 2001 From: Ravulapati Vishnu vardhan rao Date: Fri, 10 May 2019 07:11:07 +0530 Subject: [PATCH 014/626] ASoC: amd: Reporting accurate hw_ptr for acp3x dma acp3x dma pointer callback has issues in reporting hw_ptr. Modified logic to use linear position registers to retrieve accurate hw_ptr. Signed-off-by: Ravulapati Vishnu vardhan rao Signed-off-by: Vijendar Mukunda Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-pcm-dma.c | 41 +++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index 9775bda2a4ca..a4ade6bb5beb 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -32,6 +32,7 @@ struct i2s_stream_instance { u16 channels; u32 xfer_resolution; struct page *pg; + u64 bytescount; void __iomem *acp3x_base; }; @@ -317,6 +318,24 @@ static int acp3x_dma_open(struct snd_pcm_substream *substream) return 0; } +static u64 acp_get_byte_count(struct i2s_stream_instance *rtd, int direction) +{ + u64 byte_count; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + byte_count = rv_readl(rtd->acp3x_base + + mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH); + byte_count |= rv_readl(rtd->acp3x_base + + mmACP_BT_TX_LINEARPOSITIONCNTR_LOW); + } else { + byte_count = rv_readl(rtd->acp3x_base + + mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH); + byte_count |= rv_readl(rtd->acp3x_base + + mmACP_BT_RX_LINEARPOSITIONCNTR_LOW); + } + return byte_count; +} + static int acp3x_dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -350,18 +369,17 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream, static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream) { u32 pos = 0; - struct i2s_stream_instance *rtd = substream->runtime->private_data; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - pos = rv_readl(rtd->acp3x_base + - mmACP_BT_TX_LINKPOSITIONCNTR); - else - pos = rv_readl(rtd->acp3x_base + - mmACP_BT_RX_LINKPOSITIONCNTR); - - if (pos >= MAX_BUFFER) - pos = 0; + u32 buffersize = 0; + u64 bytescount = 0; + struct i2s_stream_instance *rtd = + substream->runtime->private_data; + buffersize = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + bytescount = acp_get_byte_count(rtd, substream->stream); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); return bytes_to_frames(substream->runtime, pos); } @@ -521,6 +539,7 @@ static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + rtd->bytescount = acp_get_byte_count(rtd, substream->stream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { rv_writel(period_bytes, rtd->acp3x_base + mmACP_BT_TX_INTR_WATERMARK_SIZE); From 927ce5c76e485e9d6e98b6ca29199a593d013793 Mon Sep 17 00:00:00 2001 From: Evan Green Date: Fri, 10 May 2019 15:39:28 -0700 Subject: [PATCH 015/626] ASoC: SOF: Add Comet Lake PCI IDs Add support for Intel Comet Lake platforms by adding a new Kconfig for CometLake and the appropriate PCI IDs. Signed-off-by: Evan Green Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 32 ++++++++++++++++++++++++++++++++ sound/soc/sof/sof-pci-dev.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 32ee0fabab92..25c472e6bc22 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -24,6 +24,8 @@ config SND_SOC_SOF_INTEL_PCI select SND_SOC_SOF_CANNONLAKE if SND_SOC_SOF_CANNONLAKE_SUPPORT select SND_SOC_SOF_COFFEELAKE if SND_SOC_SOF_COFFEELAKE_SUPPORT select SND_SOC_SOF_ICELAKE if SND_SOC_SOF_ICELAKE_SUPPORT + select SND_SOC_SOF_COMETLAKE_LP if SND_SOC_SOF_COMETLAKE_LP_SUPPORT + select SND_SOC_SOF_COMETLAKE_H if SND_SOC_SOF_COMETLAKE_H_SUPPORT help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -179,6 +181,36 @@ config SND_SOC_SOF_ICELAKE This option is not user-selectable but automagically handled by 'select' statements at a higher level +config SND_SOC_SOF_COMETLAKE_LP + tristate + select SND_SOC_SOF_HDA_COMMON + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level + +config SND_SOC_SOF_COMETLAKE_LP_SUPPORT + bool "SOF support for CometLake-LP" + help + This adds support for Sound Open Firmware for Intel(R) platforms + using the Cometlake-LP processors. + Say Y if you have such a device. + If unsure select "N". + +config SND_SOC_SOF_COMETLAKE_H + tristate + select SND_SOC_SOF_HDA_COMMON + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level + +config SND_SOC_SOF_COMETLAKE_H_SUPPORT + bool "SOF support for CometLake-H" + help + This adds support for Sound Open Firmware for Intel(R) platforms + using the Cometlake-H processors. + Say Y if you have such a device. + If unsure select "N". + config SND_SOC_SOF_HDA_COMMON tristate select SND_SOC_SOF_INTEL_COMMON diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index b778dffb2d25..d736806c2e0d 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -129,6 +129,26 @@ static const struct sof_dev_desc cfl_desc = { }; #endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) || \ + IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H) + +static const struct sof_dev_desc cml_desc = { + .machines = snd_soc_acpi_intel_cnl_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = -1, + .resindex_imr_base = -1, + .irqindex_host_ipc = -1, + .resindex_dma_base = -1, + .chip_info = &cnl_chip_info, + .default_fw_path = "intel/sof", + .default_tplg_path = "intel/sof-tplg", + .nocodec_fw_filename = "sof-cnl.ri", + .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", + .ops = &sof_cnl_ops, + .arch_ops = &sof_xtensa_arch_ops +}; +#endif + #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) static const struct sof_dev_desc icl_desc = { .machines = snd_soc_acpi_intel_icl_machines, @@ -353,6 +373,14 @@ static const struct pci_device_id sof_pci_ids[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) { PCI_DEVICE(0x8086, 0x34C8), .driver_data = (unsigned long)&icl_desc}, +#endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) + { PCI_DEVICE(0x8086, 0x02c8), + .driver_data = (unsigned long)&cml_desc}, +#endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H) + { PCI_DEVICE(0x8086, 0x06c8), + .driver_data = (unsigned long)&cml_desc}, #endif { 0, } }; From 5f740b243014f54e503ea5aca0a90680b56d0134 Mon Sep 17 00:00:00 2001 From: Evan Green Date: Fri, 10 May 2019 15:39:29 -0700 Subject: [PATCH 016/626] ASoC: Intel: Skylake: Add Cometlake PCI IDs Add PCI IDs for Intel CometLake platforms, which from a software point of view are extremely similar to Cannonlake platforms. Signed-off-by: Evan Green Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 16 ++++++++++++++++ sound/soc/intel/skylake/skl-messages.c | 16 ++++++++++++++++ sound/soc/intel/skylake/skl.c | 10 ++++++++++ 3 files changed, 42 insertions(+) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index fc1396adde71..b089ed3bf77f 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -165,6 +165,22 @@ config SND_SOC_INTEL_CFL If you have a Intel CoffeeLake platform with the DSP enabled in the BIOS then enable this option by saying Y or m. +config SND_SOC_INTEL_CML_H + tristate "CometLake-H Platforms" + depends on PCI && ACPI + select SND_SOC_INTEL_SKYLAKE_FAMILY + help + If you have a Intel CometLake-H platform with the DSP + enabled in the BIOS then enable this option by saying Y or m. + +config SND_SOC_INTEL_CML_LP + tristate "CometLake-LP Platforms" + depends on PCI && ACPI + select SND_SOC_INTEL_SKYLAKE_FAMILY + help + If you have a Intel CometLake-LP platform with the DSP + enabled in the BIOS then enable this option by saying Y or m. + config SND_SOC_INTEL_SKYLAKE_FAMILY tristate select SND_SOC_INTEL_SKYLAKE_COMMON diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 4bf70b4429f0..df01dc952521 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -255,6 +255,22 @@ static const struct skl_dsp_ops dsp_ops[] = { .init_fw = cnl_sst_init_fw, .cleanup = cnl_sst_dsp_cleanup }, + { + .id = 0x02c8, + .num_cores = 4, + .loader_ops = bxt_get_loader_ops, + .init = cnl_sst_dsp_init, + .init_fw = cnl_sst_init_fw, + .cleanup = cnl_sst_dsp_cleanup + }, + { + .id = 0x06c8, + .num_cores = 4, + .loader_ops = bxt_get_loader_ops, + .init = cnl_sst_dsp_init, + .init_fw = cnl_sst_init_fw, + .cleanup = cnl_sst_dsp_cleanup + }, }; const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 4ed5b7e17d44..f864f7b3df3a 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -1166,6 +1166,16 @@ static const struct pci_device_id skl_ids[] = { /* CFL */ { PCI_DEVICE(0x8086, 0xa348), .driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines}, +#endif +#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_LP) + /* CML-LP */ + { PCI_DEVICE(0x8086, 0x02c8), + .driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines}, +#endif +#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_H) + /* CML-H */ + { PCI_DEVICE(0x8086, 0x06c8), + .driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines}, #endif { 0, } }; From 5160217ba66c8eafc7479fa3439f3dc1f126d08a Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Thu, 9 May 2019 15:10:22 -0500 Subject: [PATCH 017/626] ASoC: SOF: uapi: remove unused sof header files These header files are not used by kernel but internally by SOF firmware and possibly by user space applications. If needed, they should be included from include dir exported by SOF. Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/uapi/sound/sof/eq.h | 172 --------------------------- include/uapi/sound/sof/manifest.h | 188 ------------------------------ include/uapi/sound/sof/tone.h | 21 ---- include/uapi/sound/sof/trace.h | 66 ----------- 4 files changed, 447 deletions(-) delete mode 100644 include/uapi/sound/sof/eq.h delete mode 100644 include/uapi/sound/sof/manifest.h delete mode 100644 include/uapi/sound/sof/tone.h delete mode 100644 include/uapi/sound/sof/trace.h diff --git a/include/uapi/sound/sof/eq.h b/include/uapi/sound/sof/eq.h deleted file mode 100644 index 666c2b6a3229..000000000000 --- a/include/uapi/sound/sof/eq.h +++ /dev/null @@ -1,172 +0,0 @@ -/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - */ - -#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_EQ_H__ -#define __INCLUDE_UAPI_SOUND_SOF_USER_EQ_H__ - -/* FIR EQ type */ - -#define SOF_EQ_FIR_IDX_SWITCH 0 - -#define SOF_EQ_FIR_MAX_SIZE 4096 /* Max size allowed for coef data in bytes */ - -#define SOF_EQ_FIR_MAX_LENGTH 192 /* Max length for individual filter */ - -#define SOF_EQ_FIR_MAX_RESPONSES 8 /* A blob can define max 8 FIR EQs */ - -/* - * eq_fir_configuration data structure contains this information - * uint32_t size - * This is the number of bytes need to store the received EQ - * configuration. - * uint16_t channels_in_config - * This describes the number of channels in this EQ config data. It - * can be different from PLATFORM_MAX_CHANNELS. - * uint16_t number_of_responses - * 0=no responses, 1=one response defined, 2=two responses defined, etc. - * int16_t data[] - * assign_response[channels_in_config] - * 0 = use first response, 1 = use 2nd response, etc. - * E.g. {0, 0, 0, 0, 1, 1, 1, 1} would apply to channels 0-3 the - * same first defined response and for to channels 4-7 the second. - * coef_data[] - * Repeated data - * { filter_length, output_shift, h[] } - * for every EQ response defined where vector h has filter_length - * number of coefficients. Coefficients in h[] are in Q1.15 format. - * E.g. 16384 (Q1.15) = 0.5. The shifts are number of right shifts. - * - * NOTE: The channels_in_config must be even to have coef_data aligned to - * 32 bit word in RAM. Therefore a mono EQ assign must be duplicated to 2ch - * even if it would never used. Similarly a 5ch EQ assign must be increased - * to 6ch. EQ init will return an error if this is not met. - * - * NOTE: The filter_length must be multiple of four. Therefore the filter must - * be padded from the end with zeros have this condition met. - */ - -struct sof_eq_fir_config { - uint32_t size; - uint16_t channels_in_config; - uint16_t number_of_responses; - - /* reserved */ - uint32_t reserved[4]; - - int16_t data[]; -} __packed; - -struct sof_eq_fir_coef_data { - int16_t length; /* Number of FIR taps */ - int16_t out_shift; /* Amount of right shifts at output */ - - /* reserved */ - uint32_t reserved[4]; - - int16_t coef[]; /* FIR coefficients */ -} __packed; - -/* In the struct above there's two 16 bit words (length, shift) and four - * reserved 32 bit words before the actual FIR coefficients. This information - * is used in parsing of the configuration blob. - */ -#define SOF_EQ_FIR_COEF_NHEADER \ - (sizeof(struct sof_eq_fir_coef_data) / sizeof(int16_t)) - -/* IIR EQ type */ - -#define SOF_EQ_IIR_IDX_SWITCH 0 - -#define SOF_EQ_IIR_MAX_SIZE 1024 /* Max size allowed for coef data in bytes */ - -#define SOF_EQ_IIR_MAX_RESPONSES 8 /* A blob can define max 8 IIR EQs */ - -/* eq_iir_configuration - * uint32_t channels_in_config - * This describes the number of channels in this EQ config data. It - * can be different from PLATFORM_MAX_CHANNELS. - * uint32_t number_of_responses_defined - * 0=no responses, 1=one response defined, 2=two responses defined, etc. - * int32_t data[] - * Data consist of two parts. First is the response assign vector that - * has length of channels_in_config. The latter part is coefficient - * data. - * uint32_t assign_response[channels_in_config] - * -1 = not defined, 0 = use first response, 1 = use 2nd, etc. - * E.g. {0, 0, 0, 0, -1, -1, -1, -1} would apply to channels 0-3 the - * same first defined response and leave channels 4-7 unequalized. - * coefficient_data[] - * <1st EQ> - * uint32_t num_biquads - * uint32_t num_biquads_in_series - * <1st biquad> - * int32_t coef_a2 Q2.30 format - * int32_t coef_a1 Q2.30 format - * int32_t coef_b2 Q2.30 format - * int32_t coef_b1 Q2.30 format - * int32_t coef_b0 Q2.30 format - * int32_t output_shift number of shifts right, shift left is negative - * int32_t output_gain Q2.14 format - * <2nd biquad> - * ... - * <2nd EQ> - * - * Note: A flat response biquad can be made with a section set to - * b0 = 1.0, gain = 1.0, and other parameters set to 0 - * {0, 0, 0, 0, 1073741824, 0, 16484} - */ - -struct sof_eq_iir_config { - uint32_t size; - uint32_t channels_in_config; - uint32_t number_of_responses; - - /* reserved */ - uint32_t reserved[4]; - - int32_t data[]; /* eq_assign[channels], eq 0, eq 1, ... */ -} __packed; - -struct sof_eq_iir_header_df2t { - uint32_t num_sections; - uint32_t num_sections_in_series; - - /* reserved */ - uint32_t reserved[4]; - - int32_t biquads[]; /* Repeated biquad coefficients */ -} __packed; - -struct sof_eq_iir_biquad_df2t { - int32_t a2; /* Q2.30 */ - int32_t a1; /* Q2.30 */ - int32_t b2; /* Q2.30 */ - int32_t b1; /* Q2.30 */ - int32_t b0; /* Q2.30 */ - int32_t output_shift; /* Number of right shifts */ - int32_t output_gain; /* Q2.14 */ -} __packed; - -/* A full 22th order equalizer with 11 biquads cover octave bands 1-11 in - * in the 0 - 20 kHz bandwidth. - */ -#define SOF_EQ_IIR_DF2T_BIQUADS_MAX 11 - -/* The number of int32_t words in sof_eq_iir_header_df2t: - * num_sections, num_sections_in_series, reserved[4] - */ -#define SOF_EQ_IIR_NHEADER_DF2T \ - (sizeof(struct sof_eq_iir_header_df2t) / sizeof(int32_t)) - -/* The number of int32_t words in sof_eq_iir_biquad_df2t: - * a2, a1, b2, b1, b0, output_shift, output_gain - */ -#define SOF_EQ_IIR_NBIQUAD_DF2T \ - (sizeof(struct sof_eq_iir_biquad_df2t) / sizeof(int32_t)) - -#endif diff --git a/include/uapi/sound/sof/manifest.h b/include/uapi/sound/sof/manifest.h deleted file mode 100644 index 2009ee30fad0..000000000000 --- a/include/uapi/sound/sof/manifest.h +++ /dev/null @@ -1,188 +0,0 @@ -/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - */ - -#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_MANIFEST_H__ -#define __INCLUDE_UAPI_SOUND_SOF_USER_MANIFEST_H__ - -/* start offset for base FW module */ -#define SOF_MAN_ELF_TEXT_OFFSET 0x2000 - -/* FW Extended Manifest Header id = $AE1 */ -#define SOF_MAN_EXT_HEADER_MAGIC 0x31454124 - -/* module type load type */ -#define SOF_MAN_MOD_TYPE_BUILTIN 0 -#define SOF_MAN_MOD_TYPE_MODULE 1 - -struct sof_man_module_type { - uint32_t load_type:4; /* SOF_MAN_MOD_TYPE_ */ - uint32_t auto_start:1; - uint32_t domain_ll:1; - uint32_t domain_dp:1; - uint32_t rsvd_:25; -}; - -/* segment flags.type */ -#define SOF_MAN_SEGMENT_TEXT 0 -#define SOF_MAN_SEGMENT_RODATA 1 -#define SOF_MAN_SEGMENT_DATA 1 -#define SOF_MAN_SEGMENT_BSS 2 -#define SOF_MAN_SEGMENT_EMPTY 15 - -union sof_man_segment_flags { - uint32_t ul; - struct { - uint32_t contents:1; - uint32_t alloc:1; - uint32_t load:1; - uint32_t readonly:1; - uint32_t code:1; - uint32_t data:1; - uint32_t _rsvd0:2; - uint32_t type:4; /* MAN_SEGMENT_ */ - uint32_t _rsvd1:4; - uint32_t length:16; /* of segment in pages */ - } r; -} __packed; - -/* - * Module segment descriptor. Used by ROM - Immutable. - */ -struct sof_man_segment_desc { - union sof_man_segment_flags flags; - uint32_t v_base_addr; - uint32_t file_offset; -} __packed; - -/* - * The firmware binary can be split into several modules. - */ - -#define SOF_MAN_MOD_ID_LEN 4 -#define SOF_MAN_MOD_NAME_LEN 8 -#define SOF_MAN_MOD_SHA256_LEN 32 -#define SOF_MAN_MOD_ID {'$', 'A', 'M', 'E'} - -/* - * Each module has an entry in the FW header. Used by ROM - Immutable. - */ -struct sof_man_module { - uint8_t struct_id[SOF_MAN_MOD_ID_LEN]; /* SOF_MAN_MOD_ID */ - uint8_t name[SOF_MAN_MOD_NAME_LEN]; - uint8_t uuid[16]; - struct sof_man_module_type type; - uint8_t hash[SOF_MAN_MOD_SHA256_LEN]; - uint32_t entry_point; - uint16_t cfg_offset; - uint16_t cfg_count; - uint32_t affinity_mask; - uint16_t instance_max_count; /* max number of instances */ - uint16_t instance_bss_size; /* instance (pages) */ - struct sof_man_segment_desc segment[3]; -} __packed; - -/* - * Each module has a configuration in the FW header. Used by ROM - Immutable. - */ -struct sof_man_mod_config { - uint32_t par[4]; /* module parameters */ - uint32_t is_pages; /* actual size of instance .bss (pages) */ - uint32_t cps; /* cycles per second */ - uint32_t ibs; /* input buffer size (bytes) */ - uint32_t obs; /* output buffer size (bytes) */ - uint32_t module_flags; /* flags, reserved for future use */ - uint32_t cpc; /* cycles per single run */ - uint32_t obls; /* output block size, reserved for future use */ -} __packed; - -/* - * FW Manifest Header - */ - -#define SOF_MAN_FW_HDR_FW_NAME_LEN 8 -#define SOF_MAN_FW_HDR_ID {'$', 'A', 'M', '1'} -#define SOF_MAN_FW_HDR_NAME "ADSPFW" -#define SOF_MAN_FW_HDR_FLAGS 0x0 -#define SOF_MAN_FW_HDR_FEATURES 0xff - -/* - * The firmware has a standard header that is checked by the ROM on firmware - * loading. preload_page_count is used by DMA code loader and is entire - * image size on CNL. i.e. CNL: total size of the binary’s .text and .rodata - * Used by ROM - Immutable. - */ -struct sof_man_fw_header { - uint8_t header_id[4]; - uint32_t header_len; - uint8_t name[SOF_MAN_FW_HDR_FW_NAME_LEN]; - /* number of pages of preloaded image loaded by driver */ - uint32_t preload_page_count; - uint32_t fw_image_flags; - uint32_t feature_mask; - uint16_t major_version; - uint16_t minor_version; - uint16_t hotfix_version; - uint16_t build_version; - uint32_t num_module_entries; - uint32_t hw_buf_base_addr; - uint32_t hw_buf_length; - /* target address for binary loading as offset in IMR - must be == base offset */ - uint32_t load_offset; -} __packed; - -/* - * Firmware manifest descriptor. This can contain N modules and N module - * configs. Used by ROM - Immutable. - */ -struct sof_man_fw_desc { - struct sof_man_fw_header header; - - /* Warning - hack for module arrays. For some unknown reason the we - * have a variable size array of struct man_module followed by a - * variable size array of struct mod_config. These should have been - * merged into a variable array of a parent structure. We have to hack - * around this in many places.... - * - * struct sof_man_module man_module[]; - * struct sof_man_mod_config mod_config[]; - */ - -} __packed; - -/* - * Component Descriptor. Used by ROM - Immutable. - */ -struct sof_man_component_desc { - uint32_t reserved[2]; /* all 0 */ - uint32_t version; - uint8_t hash[SOF_MAN_MOD_SHA256_LEN]; - uint32_t base_offset; - uint32_t limit_offset; - uint32_t attributes[4]; -} __packed; - -/* - * Audio DSP extended metadata. Used by ROM - Immutable. - */ -struct sof_man_adsp_meta_file_ext { - uint32_t ext_type; /* always 17 for ADSP extension */ - uint32_t ext_len; - uint32_t imr_type; - uint8_t reserved[16]; /* all 0 */ - struct sof_man_component_desc comp_desc[1]; -} __packed; - -/* - * Module Manifest for rimage module metadata. Not used by ROM. - */ -struct sof_man_module_manifest { - struct sof_man_module module; - uint32_t text_size; -} __packed; - -#endif diff --git a/include/uapi/sound/sof/tone.h b/include/uapi/sound/sof/tone.h deleted file mode 100644 index d7c6e5d8317e..000000000000 --- a/include/uapi/sound/sof/tone.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ -/* -* This file is provided under a dual BSD/GPLv2 license. When using or -* redistributing this file, you may do so under either license. -* -* Copyright(c) 2018 Intel Corporation. All rights reserved. -*/ - -#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_TONE_H__ -#define __INCLUDE_UAPI_SOUND_SOF_USER_TONE_H__ - -#define SOF_TONE_IDX_FREQUENCY 0 -#define SOF_TONE_IDX_AMPLITUDE 1 -#define SOF_TONE_IDX_FREQ_MULT 2 -#define SOF_TONE_IDX_AMPL_MULT 3 -#define SOF_TONE_IDX_LENGTH 4 -#define SOF_TONE_IDX_PERIOD 5 -#define SOF_TONE_IDX_REPEATS 6 -#define SOF_TONE_IDX_LIN_RAMP_STEP 7 - -#endif diff --git a/include/uapi/sound/sof/trace.h b/include/uapi/sound/sof/trace.h deleted file mode 100644 index ffa7288a0f16..000000000000 --- a/include/uapi/sound/sof/trace.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - */ - -#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_TRACE_H__ -#define __INCLUDE_UAPI_SOUND_SOF_USER_TRACE_H__ - -/* - * Host system time. - * - * This property is used by the driver to pass down information about - * current system time. It is expressed in us. - * FW translates timestamps (in log entries, probe pockets) to this time - * domain. - * - * (cavs: SystemTime). - */ -struct system_time { - uint32_t val_l; /* Lower dword of current host time value */ - uint32_t val_u; /* Upper dword of current host time value */ -} __packed; - -#define LOG_ENABLE 1 /* Enable logging */ -#define LOG_DISABLE 0 /* Disable logging */ - -#define LOG_LEVEL_CRITICAL 1 /* (FDK fatal) */ -#define LOG_LEVEL_VERBOSE 2 - -/* - * Layout of a log fifo. - */ -struct log_buffer_layout { - uint32_t read_ptr; /*read pointer */ - uint32_t write_ptr; /* write pointer */ - uint32_t buffer[0]; /* buffer */ -} __packed; - -/* - * Log buffer status reported by FW. - */ -struct log_buffer_status { - uint32_t core_id; /* ID of core that logged to other half */ -} __packed; - -#define TRACE_ID_LENGTH 12 - -/* - * Log entry header. - * - * The header is followed by an array of arguments (uint32_t[]). - * Number of arguments is specified by the params_num field of log_entry - */ -struct log_entry_header { - uint32_t id_0 : TRACE_ID_LENGTH; /* e.g. Pipeline ID */ - uint32_t id_1 : TRACE_ID_LENGTH; /* e.g. Component ID */ - uint32_t core_id : 8; /* Reporting core's id */ - - uint64_t timestamp; /* Timestamp (in dsp ticks) */ - uint32_t log_entry_address; /* Address of log entry in ELF */ -} __packed; - -#endif From 14a2212dd4bcb55a03eddaf66d62068c9cece585 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 9 May 2019 15:10:24 -0500 Subject: [PATCH 018/626] ASoC: SOF: pcm: remove runtime PM calls during pcm open/close pm_runtime_get_sync()/pm_runtime_put_autosuspend() calls are already invoked by the ASoC core in soc_pcm_open() and soc_pcm_close(). So the SOF component driver does not need to call them again. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 649968841dad..4f536c0de0a5 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -416,7 +416,6 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) struct snd_sof_pcm *spcm; struct snd_soc_tplg_stream_caps *caps; int ret; - int err; /* nothing to do for BE */ if (rtd->dai_link->no_pcm) @@ -434,14 +433,6 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) caps = &spcm->pcm.caps[substream->stream]; - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "error: pcm open failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } - /* set any runtime constraints based on topology */ snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, @@ -485,17 +476,8 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) spcm->stream[substream->stream].substream = substream; ret = snd_sof_pcm_platform_open(sdev, substream); - if (ret < 0) { - dev_err(sdev->dev, "error: pcm open failed %d\n", - ret); - - pm_runtime_mark_last_busy(sdev->dev); - - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err(sdev->dev, "error: pcm close failed to idle %d\n", - err); - } + if (ret < 0) + dev_err(sdev->dev, "error: pcm open failed %d\n", ret); return ret; } @@ -530,13 +512,6 @@ static int sof_pcm_close(struct snd_pcm_substream *substream) */ } - pm_runtime_mark_last_busy(sdev->dev); - - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err(sdev->dev, "error: pcm close failed to idle %d\n", - err); - return 0; } From ec836daafcdf371882f08cc05c522662409e90ae Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Thu, 9 May 2019 15:10:26 -0500 Subject: [PATCH 019/626] ASoC: SOF: Intel: ICL: add Icelake SSP count On Icelake we have 6 SSP ports, add ICL SSP count to enable all SSPs, instead of using the SSP count defined for CNL. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 92d45c43b4b1..15ea50aff4ea 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -348,6 +348,7 @@ /* SSP Count of the Platform */ #define APL_SSP_COUNT 6 #define CNL_SSP_COUNT 3 +#define ICL_SSP_COUNT 6 /* SSP Registers */ #define SSP_SSC1_OFFSET 0x4 From 630be964b5d8d37d3dff9fc5c8af8a516aa94af0 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Thu, 9 May 2019 15:10:27 -0500 Subject: [PATCH 020/626] ASoC: SOF: Intel: ICL add Icelake chip info struct Icelake has different count of SSP other than CNL, using the new defined ICL SSP count, and copy other parameters from CNL chip info. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 19 +++++++++++++++++++ sound/soc/sof/intel/hda.h | 1 + sound/soc/sof/sof-pci-dev.c | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 08a1a3d3c08d..c059d1170bab 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -266,3 +266,22 @@ const struct sof_intel_dsp_desc cnl_chip_info = { .ssp_base_offset = CNL_SSP_BASE_OFFSET, }; EXPORT_SYMBOL(cnl_chip_info); + +const struct sof_intel_dsp_desc icl_chip_info = { + /* Icelake */ + .cores_num = 4, + .init_core_mask = 1, + .cores_mask = HDA_DSP_CORE_MASK(0) | + HDA_DSP_CORE_MASK(1) | + HDA_DSP_CORE_MASK(2) | + HDA_DSP_CORE_MASK(3), + .ipc_req = CNL_DSP_REG_HIPCIDR, + .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY, + .ipc_ack = CNL_DSP_REG_HIPCIDA, + .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, + .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_init_timeout = 300, + .ssp_count = ICL_SSP_COUNT, + .ssp_base_offset = CNL_SSP_BASE_OFFSET, +}; +EXPORT_SYMBOL(icl_chip_info); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 15ea50aff4ea..455046612b94 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -580,5 +580,6 @@ extern const struct snd_sof_dsp_ops sof_skl_ops; extern const struct sof_intel_dsp_desc apl_chip_info; extern const struct sof_intel_dsp_desc cnl_chip_info; extern const struct sof_intel_dsp_desc skl_chip_info; +extern const struct sof_intel_dsp_desc icl_chip_info; #endif diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index d736806c2e0d..e2b19782f01a 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -157,7 +157,7 @@ static const struct sof_dev_desc icl_desc = { .resindex_imr_base = -1, .irqindex_host_ipc = -1, .resindex_dma_base = -1, - .chip_info = &cnl_chip_info, + .chip_info = &icl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .nocodec_fw_filename = "sof-icl.ri", From bcd9382288af236321c83d27b0db196bf8814559 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 9 May 2019 11:04:54 +0800 Subject: [PATCH 021/626] ASoC: max98357a: request GPIO when device get probed devm_gpiod_get_optional() returns EBUSY after component rebound. Request GPIO in max98357a_platform_probe() to support component rebinding. Signed-off-by: Tzung-Bi Shih Signed-off-by: Mark Brown --- sound/soc/codecs/max98357a.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index d037a3e4d323..80080a6415b3 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -59,21 +59,7 @@ static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { {"Speaker", NULL, "HiFi Playback"}, }; -static int max98357a_component_probe(struct snd_soc_component *component) -{ - struct gpio_desc *sdmode; - - sdmode = devm_gpiod_get_optional(component->dev, "sdmode", GPIOD_OUT_LOW); - if (IS_ERR(sdmode)) - return PTR_ERR(sdmode); - - snd_soc_component_set_drvdata(component, sdmode); - - return 0; -} - static const struct snd_soc_component_driver max98357a_component_driver = { - .probe = max98357a_component_probe, .dapm_widgets = max98357a_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), .dapm_routes = max98357a_dapm_routes, @@ -112,16 +98,20 @@ static struct snd_soc_dai_driver max98357a_dai_driver = { static int max98357a_platform_probe(struct platform_device *pdev) { + struct gpio_desc *sdmode; + + sdmode = devm_gpiod_get_optional(&pdev->dev, + "sdmode", GPIOD_OUT_LOW); + if (IS_ERR(sdmode)) + return PTR_ERR(sdmode); + + dev_set_drvdata(&pdev->dev, sdmode); + return devm_snd_soc_register_component(&pdev->dev, &max98357a_component_driver, &max98357a_dai_driver, 1); } -static int max98357a_platform_remove(struct platform_device *pdev) -{ - return 0; -} - #ifdef CONFIG_OF static const struct of_device_id max98357a_device_id[] = { { .compatible = "maxim,max98357a" }, @@ -145,7 +135,6 @@ static struct platform_driver max98357a_platform_driver = { .acpi_match_table = ACPI_PTR(max98357a_acpi_match), }, .probe = max98357a_platform_probe, - .remove = max98357a_platform_remove, }; module_platform_driver(max98357a_platform_driver); From 22d251a5964780452aed378a143816fbf2d4201d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:06:07 +0900 Subject: [PATCH 022/626] ASoC: soc-core: use i on snd_soc_resume() This patch uses "int i" instead of "int j" on snd_soc_resume(), and moves struct snd_soc_dai *codec_dai to top of this function. This is cleanup and prepare for Multi CPU support Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2403bec2fccf..0d9b02075050 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -687,6 +687,8 @@ int snd_soc_resume(struct device *dev) struct snd_soc_card *card = dev_get_drvdata(dev); bool bus_control = false; struct snd_soc_pcm_runtime *rtd; + struct snd_soc_dai *codec_dai; + int i; /* If the card is not initialized yet there is nothing to do */ if (!card->instantiated) @@ -694,14 +696,12 @@ int snd_soc_resume(struct device *dev) /* activate pins from sleep state */ for_each_card_rtds(card, rtd) { - struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int j; if (cpu_dai->active) pinctrl_pm_select_default_state(cpu_dai->dev); - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dai(rtd, i, codec_dai) { if (codec_dai->active) pinctrl_pm_select_default_state(codec_dai->dev); } From 0a2cfcd998e3503c20be497cadb0ef23edb984be Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:06:30 +0900 Subject: [PATCH 023/626] ASoC: soc-core: don't use codec_dais on soc_bind_dai_link() Current soc_bind_dai_link() is substituting rtd->codec_dais to codec_dais, and sets found DAI into it. But, it is a little bit un-readable / un-understandable to know detail of rtd, and it will make difficult to understand rtd->cpu_dais if Multi CPU was supported. This patch cleanup it and prepare for Multi CPU support. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0d9b02075050..2ceca7fdf622 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -878,7 +878,6 @@ static int soc_bind_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link_component *codecs; struct snd_soc_dai_link_component cpu_dai_component; struct snd_soc_component *component; - struct snd_soc_dai **codec_dais; int i; if (dai_link->ignore) @@ -910,19 +909,18 @@ static int soc_bind_dai_link(struct snd_soc_card *card, rtd->num_codecs = dai_link->num_codecs; /* Find CODEC from registered CODECs */ - codec_dais = rtd->codec_dais; for_each_link_codecs(dai_link, i, codecs) { - codec_dais[i] = snd_soc_find_dai(codecs); - if (!codec_dais[i]) { + rtd->codec_dais[i] = snd_soc_find_dai(codecs); + if (!rtd->codec_dais[i]) { dev_info(card->dev, "ASoC: CODEC DAI %s not registered\n", codecs->dai_name); goto _err_defer; } - snd_soc_rtdcom_add(rtd, codec_dais[i]->component); + snd_soc_rtdcom_add(rtd, rtd->codec_dais[i]->component); } /* Single codec links expect codec and codec_dai in runtime data */ - rtd->codec_dai = codec_dais[0]; + rtd->codec_dai = rtd->codec_dais[0]; /* find one from the set of registered platforms */ for_each_component(component) { From e2b30edfb9435879dc68cdb7ce20299492012101 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:06:44 +0900 Subject: [PATCH 024/626] ASoC: soc-core: tidyup soc_bind_dai_link() comment balance Many code at soc_bind_dai_link() was changed, and its comment is now a little bit anbalanced. This patch tidyup these. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2ceca7fdf622..c80e7df3b20b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -906,9 +906,8 @@ static int soc_bind_dai_link(struct snd_soc_card *card, } snd_soc_rtdcom_add(rtd, rtd->cpu_dai->component); - rtd->num_codecs = dai_link->num_codecs; - /* Find CODEC from registered CODECs */ + rtd->num_codecs = dai_link->num_codecs; for_each_link_codecs(dai_link, i, codecs) { rtd->codec_dais[i] = snd_soc_find_dai(codecs); if (!rtd->codec_dais[i]) { @@ -922,7 +921,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, /* Single codec links expect codec and codec_dai in runtime data */ rtd->codec_dai = rtd->codec_dais[0]; - /* find one from the set of registered platforms */ + /* Find PLATFORM from registered PLATFORMs */ for_each_component(component) { if (!snd_soc_is_matching_component(dai_link->platforms, component)) From c083444061ada428af71809cc12fd8f06dd2be19 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:06:59 +0900 Subject: [PATCH 025/626] ASoC: soc-core: add soc_component_to_node() Many function are getting device_node from component with caring its parent component. This patch adds new soc_component_to_node() and share same code. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c80e7df3b20b..e55170ce6d3e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -738,6 +738,18 @@ EXPORT_SYMBOL_GPL(snd_soc_resume); static const struct snd_soc_dai_ops null_dai_ops = { }; +static struct device_node +*soc_component_to_node(struct snd_soc_component *component) +{ + struct device_node *of_node; + + of_node = component->dev->of_node; + if (!of_node && component->dev->parent) + of_node = component->dev->parent->of_node; + + return of_node; +} + static struct snd_soc_component *soc_find_component( const struct device_node *of_node, const char *name) { @@ -748,9 +760,7 @@ static struct snd_soc_component *soc_find_component( for_each_component(component) { if (of_node) { - component_of_node = component->dev->of_node; - if (!component_of_node && component->dev->parent) - component_of_node = component->dev->parent->of_node; + component_of_node = soc_component_to_node(component); if (component_of_node == of_node) return component; @@ -768,9 +778,7 @@ static int snd_soc_is_matching_component( { struct device_node *component_of_node; - component_of_node = component->dev->of_node; - if (!component_of_node && component->dev->parent) - component_of_node = component->dev->parent->of_node; + component_of_node = soc_component_to_node(component); if (dlc->of_node && component_of_node != dlc->of_node) return 0; @@ -1317,13 +1325,10 @@ EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link); static void soc_set_of_name_prefix(struct snd_soc_component *component) { - struct device_node *component_of_node = component->dev->of_node; + struct device_node *component_of_node = soc_component_to_node(component); const char *str; int ret; - if (!component_of_node && component->dev->parent) - component_of_node = component->dev->parent->of_node; - ret = of_property_read_string(component_of_node, "sound-name-prefix", &str); if (!ret) @@ -1337,10 +1342,7 @@ static void soc_set_name_prefix(struct snd_soc_card *card, for (i = 0; i < card->num_configs && card->codec_conf; i++) { struct snd_soc_codec_conf *map = &card->codec_conf[i]; - struct device_node *component_of_node = component->dev->of_node; - - if (!component_of_node && component->dev->parent) - component_of_node = component->dev->parent->of_node; + struct device_node *component_of_node = soc_component_to_node(component); if (map->of_node && component_of_node != map->of_node) continue; @@ -3764,10 +3766,7 @@ int snd_soc_get_dai_id(struct device_node *ep) ret = -ENOTSUPP; mutex_lock(&client_mutex); for_each_component(pos) { - struct device_node *component_of_node = pos->dev->of_node; - - if (!component_of_node && pos->dev->parent) - component_of_node = pos->dev->parent->of_node; + struct device_node *component_of_node = soc_component_to_node(pos); if (component_of_node != node) continue; @@ -3794,9 +3793,7 @@ int snd_soc_get_dai_name(struct of_phandle_args *args, mutex_lock(&client_mutex); for_each_component(pos) { - component_of_node = pos->dev->of_node; - if (!component_of_node && pos->dev->parent) - component_of_node = pos->dev->parent->of_node; + component_of_node = soc_component_to_node(pos); if (component_of_node != args->np) continue; From 09d4cc03ff77790872b8b9e51b6d7b5863686fc5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:07:20 +0900 Subject: [PATCH 026/626] ASoC: soc-core: use soc_find_component() at snd_soc_get_dai_id() soc-core core already has soc_find_component() which find component from device node. Let's use existing function to find component. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e55170ce6d3e..e83edbe27041 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3751,7 +3751,7 @@ EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); int snd_soc_get_dai_id(struct device_node *ep) { - struct snd_soc_component *pos; + struct snd_soc_component *component; struct device_node *node; int ret; @@ -3765,17 +3765,10 @@ int snd_soc_get_dai_id(struct device_node *ep) */ ret = -ENOTSUPP; mutex_lock(&client_mutex); - for_each_component(pos) { - struct device_node *component_of_node = soc_component_to_node(pos); - - if (component_of_node != node) - continue; - - if (pos->driver->of_xlate_dai_id) - ret = pos->driver->of_xlate_dai_id(pos, ep); - - break; - } + component = soc_find_component(node, NULL); + if (component && + component->driver->of_xlate_dai_id) + ret = component->driver->of_xlate_dai_id(component, ep); mutex_unlock(&client_mutex); of_node_put(node); From 7426af5010d1b4a109e5d7ee639f3c3e0e5b3cdd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:07:27 +0900 Subject: [PATCH 027/626] ASoC: soc.h: fe_compr can be bit field fe_compr is used at soc-compress, it can be bit field. This patch move it from int to bit field. > grep fe_compr -r sound/soc/* sound/soc/soc-compress.c: rtd->fe_compr = 1; sound/soc/soc-pcm.c: if (!fe->dpcm[stream].runtime && !fe->fe_compr) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 482b4ea87c3c..f20785aa7b4a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1214,7 +1214,6 @@ struct snd_soc_pcm_runtime { /* Dynamic PCM BE runtime data */ struct snd_soc_dpcm_runtime dpcm[2]; - int fe_compr; long pmdown_time; @@ -1239,6 +1238,7 @@ struct snd_soc_pcm_runtime { /* bit field */ unsigned int dev_registered:1; unsigned int pop_wait:1; + unsigned int fe_compr:1; /* for Dynamic PCM */ }; #define for_each_rtd_codec_dai(rtd, i, dai)\ for ((i) = 0; \ From ca58221d2212aff4f41d05b99b1e2ed288b24ccc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:07:43 +0900 Subject: [PATCH 028/626] ASoC: soc-pcm: do cpu_dai related operation at same place cpu_dai related operation is separated by component operation at soc_pcm_hw_params() somehow. It is not readable, let's do it at same place Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 0a4f60c7a188..ad560d9bf06a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -990,6 +990,14 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, if (ret < 0) goto interface_err; + /* store the parameters for each DAIs */ + cpu_dai->rate = params_rate(params); + cpu_dai->channels = params_channels(params); + cpu_dai->sample_bits = + snd_pcm_format_physical_width(params_format(params)); + + snd_soc_dapm_update_dai(substream, params, cpu_dai); + for_each_rtdcom(rtd, rtdcom) { component = rtdcom->component; @@ -1007,14 +1015,6 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, } component = NULL; - /* store the parameters for each DAIs */ - cpu_dai->rate = params_rate(params); - cpu_dai->channels = params_channels(params); - cpu_dai->sample_bits = - snd_pcm_format_physical_width(params_format(params)); - - snd_soc_dapm_update_dai(substream, params, cpu_dai); - ret = soc_pcm_params_symmetry(substream, params); if (ret) goto component_err; From 2371abdc08e491f6f540c3971bdfa8c90f3329fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:07:52 +0900 Subject: [PATCH 029/626] ASoC: soc-pcm: add missing cpu_dai->rate = 0 Codec side is setting codec_dai->rate = 0 when error case at soc_pcm_hw_params(), but there is not such setting for CPU side. This patch adds it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ad560d9bf06a..2dcc44c73f6c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1027,6 +1027,7 @@ component_err: if (cpu_dai->driver->ops->hw_free) cpu_dai->driver->ops->hw_free(substream, cpu_dai); + cpu_dai->rate = 0; interface_err: i = rtd->num_codecs; From e7ecfdb794fef1f6c91f62a40fd6aa3d4d8d2471 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 May 2019 16:08:33 +0900 Subject: [PATCH 030/626] ASoC: soc-pcm: add soc_pcm_components_open() soc-pcm.c has soc_pcm_components_close() but not have its open() side function. This kind of unbalance function is very unreadable. And, current error handling is not correct. Because it is using for_each_rtdcom() loop, we need to call soc_pcm_components_close() anyway even though CPU DAI .startup() failed. This patch adds soc_pcm_components_open(), and fixup error handling issue. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 63 ++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2dcc44c73f6c..74c7d38af2c6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -446,6 +446,42 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) hw->rate_max = min_not_zero(hw->rate_max, rate_max); } +static int soc_pcm_components_open(struct snd_pcm_substream *substream, + struct snd_soc_component **last) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_rtdcom_list *rtdcom; + struct snd_soc_component *component; + int ret = 0; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + *last = component; + + if (!component->driver->ops || + !component->driver->ops->open) + continue; + + if (component->driver->module_get_upon_open && + !try_module_get(component->dev->driver->owner)) { + dev_err(component->dev, + "ASoC: can't get module %s\n", + component->name); + return -ENODEV; + } + + ret = component->driver->ops->open(substream); + if (ret < 0) { + dev_err(component->dev, + "ASoC: can't open component %s: %d\n", + component->name, ret); + return ret; + } + } + *last = NULL; + return 0; +} + static int soc_pcm_components_close(struct snd_pcm_substream *substream, struct snd_soc_component *last) { @@ -510,28 +546,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } } - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->ops || - !component->driver->ops->open) - continue; - - if (component->driver->module_get_upon_open && - !try_module_get(component->dev->driver->owner)) { - ret = -ENODEV; - goto module_err; - } - - ret = component->driver->ops->open(substream); - if (ret < 0) { - dev_err(component->dev, - "ASoC: can't open component %s: %d\n", - component->name, ret); - goto component_err; - } - } - component = NULL; + ret = soc_pcm_components_open(substream, &component); + if (ret < 0) + goto component_err; for_each_rtd_codec_dai(rtd, i, codec_dai) { if (codec_dai->driver->ops->startup) { @@ -638,7 +655,7 @@ codec_dai_err: component_err: soc_pcm_components_close(substream, component); -module_err: + if (cpu_dai->driver->ops->shutdown) cpu_dai->driver->ops->shutdown(substream, cpu_dai); out: From eb1ecadb7f67dde94ef0efd3ddaed5cb6c9a65ed Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 13 May 2019 10:18:47 +0200 Subject: [PATCH 031/626] ASoC: hdmi-codec: re-introduce mutex locking Replace the bit atomic operations by a mutex to ensure only one dai at a time is active on the hdmi codec. This is a follow up on change: 3fcf94ef4d41 ("ASoC: hdmi-codec: remove reference to the current substream") Suggested-by: Mark Brown Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 90a892766625..6a0cc8d7e141 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -281,7 +281,7 @@ struct hdmi_codec_priv { uint8_t eld[MAX_ELD_BYTES]; struct snd_pcm_chmap *chmap_info; unsigned int chmap_idx; - unsigned long busy; + struct mutex lock; }; static const struct snd_soc_dapm_widget hdmi_widgets[] = { @@ -395,8 +395,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); int ret = 0; - ret = test_and_set_bit(0, &hcp->busy); - if (ret) { + ret = mutex_trylock(&hcp->lock); + if (!ret) { dev_err(dai->dev, "Only one simultaneous stream supported!\n"); return -EINVAL; } @@ -424,7 +424,7 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, err: /* Release the exclusive lock on error */ - clear_bit(0, &hcp->busy); + mutex_unlock(&hcp->lock); return ret; } @@ -436,7 +436,7 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); - clear_bit(0, &hcp->busy); + mutex_unlock(&hcp->lock); } static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, @@ -773,6 +773,8 @@ static int hdmi_codec_probe(struct platform_device *pdev) return -ENOMEM; hcp->hcd = *hcd; + mutex_init(&hcp->lock); + daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL); if (!daidrv) return -ENOMEM; From 1628fc3f47717fc3c8d9cd5fd6c7bc7d3796927d Mon Sep 17 00:00:00 2001 From: Shunli Wang Date: Thu, 16 May 2019 17:54:37 +0800 Subject: [PATCH 032/626] ASoC: Mediatek: add memory interface data align This supports two data align settings. One is S32_LE and other is S24_LE. Signed-off-by: Shunli Wang Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-afe-fe-dai.c | 7 +++++++ sound/soc/mediatek/common/mtk-base-afe.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index fded11d14cde..19048c3dc324 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -241,6 +241,7 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; int hd_audio = 0; + int hd_align = 1; /* set hd mode */ switch (substream->runtime->format) { @@ -249,9 +250,11 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, break; case SNDRV_PCM_FORMAT_S32_LE: hd_audio = 1; + hd_align = 1; break; case SNDRV_PCM_FORMAT_S24_LE: hd_audio = 1; + hd_align = 0; break; default: dev_err(afe->dev, "%s() error: unsupported format %d\n", @@ -262,6 +265,10 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg, 1, hd_audio, memif->data->hd_shift); + mtk_regmap_update_bits(afe->regmap, memif->data->hd_align_reg, + memif->data->hd_align_mshift, + hd_align ? memif->data->hd_align_mshift : 0); + return 0; } EXPORT_SYMBOL_GPL(mtk_afe_fe_prepare); diff --git a/sound/soc/mediatek/common/mtk-base-afe.h b/sound/soc/mediatek/common/mtk-base-afe.h index bd8d5e0c6843..60cb609a9790 100644 --- a/sound/soc/mediatek/common/mtk-base-afe.h +++ b/sound/soc/mediatek/common/mtk-base-afe.h @@ -24,7 +24,9 @@ struct mtk_base_memif_data { int enable_reg; int enable_shift; int hd_reg; + int hd_align_reg; int hd_shift; + int hd_align_mshift; int msb_reg; int msb_shift; int agent_disable_reg; From cf61f5b01531a2b64b875894fa97aa891d39e871 Mon Sep 17 00:00:00 2001 From: Shunli Wang Date: Thu, 16 May 2019 17:54:38 +0800 Subject: [PATCH 033/626] ASoC: Mediatek: MT8183: set data align This patch sets register and bit information about data align for every memory interface. Signed-off-by: Shunli Wang Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index 1bc0fafe5e29..ab2bce1d9b3d 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -437,7 +437,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = AFE_DAC_CON0, .enable_shift = DL1_ON_SFT, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = DL1_HD_SFT, + .hd_align_mshift = DL1_HD_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -456,7 +458,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = AFE_DAC_CON0, .enable_shift = DL2_ON_SFT, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = DL2_HD_SFT, + .hd_align_mshift = DL2_HD_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -475,7 +479,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = AFE_DAC_CON0, .enable_shift = DL3_ON_SFT, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = DL3_HD_SFT, + .hd_align_mshift = DL3_HD_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -494,7 +500,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = AFE_DAC_CON0, .enable_shift = VUL2_ON_SFT, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = VUL2_HD_SFT, + .hd_align_mshift = VUL2_HD_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -513,7 +521,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = AFE_DAC_CON0, .enable_shift = AWB_ON_SFT, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = AWB_HD_SFT, + .hd_align_mshift = AWB_HD_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -532,7 +542,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = AFE_DAC_CON0, .enable_shift = AWB2_ON_SFT, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = AWB2_HD_SFT, + .hd_align_mshift = AWB2_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -551,7 +563,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = AFE_DAC_CON0, .enable_shift = VUL12_ON_SFT, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = VUL12_HD_SFT, + .hd_align_mshift = VUL12_HD_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -570,7 +584,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = AFE_DAC_CON0, .enable_shift = MOD_DAI_ON_SFT, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = MOD_DAI_HD_SFT, + .hd_align_mshift = MOD_DAI_HD_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -589,7 +605,9 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .enable_reg = -1, /* control in tdm for sync start */ .enable_shift = -1, .hd_reg = AFE_MEMIF_HD_MODE, + .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = HDMI_HD_SFT, + .hd_align_mshift = HDMI_HD_ALIGN_MASK_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, From 1b74211011eb064914b8155a77a8aaae61cd27eb Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 15 May 2019 15:18:54 +0200 Subject: [PATCH 034/626] ASoC: meson: axg-card: set link name based on link node name So far the link names of the axg sound card was derived from the cpu name of the link. Since the dai link must be unique, it works as long as a device does not provide more than one cpu dai. However, the 'tohdmitx' does provide 2 dais used as cpu on codec-to-codec links Instead of cpu name, use the node name of the dai link. DT already enforce the uniqueness of this name Signed-off-by: Jerome Brunet Tested-by: Neil Armstrong Tested-by: Kevin Hilman Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index aa54d2c612c9..5c8deee8d512 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -80,10 +80,11 @@ static int axg_card_parse_dai(struct snd_soc_card *card, static int axg_card_set_link_name(struct snd_soc_card *card, struct snd_soc_dai_link *link, + struct device_node *node, const char *prefix) { char *name = devm_kasprintf(card->dev, GFP_KERNEL, "%s.%s", - prefix, link->cpu_of_node->full_name); + prefix, node->full_name); if (!name) return -ENOMEM; @@ -474,7 +475,7 @@ static int axg_card_set_be_link(struct snd_soc_card *card, codec++; } - ret = axg_card_set_link_name(card, link, "be"); + ret = axg_card_set_link_name(card, link, node, "be"); if (ret) dev_err(card->dev, "error setting %pOFn link name\n", np); @@ -483,6 +484,7 @@ static int axg_card_set_be_link(struct snd_soc_card *card, static int axg_card_set_fe_link(struct snd_soc_card *card, struct snd_soc_dai_link *link, + struct device_node *node, bool is_playback) { link->dynamic = 1; @@ -497,7 +499,7 @@ static int axg_card_set_fe_link(struct snd_soc_card *card, else link->dpcm_capture = 1; - return axg_card_set_link_name(card, link, "fe"); + return axg_card_set_link_name(card, link, node, "fe"); } static int axg_card_cpu_is_capture_fe(struct device_node *np) @@ -527,9 +529,9 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, return ret; if (axg_card_cpu_is_playback_fe(dai_link->cpu_of_node)) - ret = axg_card_set_fe_link(card, dai_link, true); + ret = axg_card_set_fe_link(card, dai_link, np, true); else if (axg_card_cpu_is_capture_fe(dai_link->cpu_of_node)) - ret = axg_card_set_fe_link(card, dai_link, false); + ret = axg_card_set_fe_link(card, dai_link, np, false); else ret = axg_card_set_be_link(card, dai_link, np); From c3456a4b2142550944f73a87a8f338074508b249 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 15 May 2019 15:18:55 +0200 Subject: [PATCH 035/626] ASoC: dapm: allow muxes to force a disconnect Let soc_dapm_mux_update_power() accept NULL as 'e' enum. It makes the code a bit more robust and, more importantly, let the calling mux force a disconnect of the output path if necessary. This is useful if the dapm elements following the mux must be off while updating the mux, to avoid glitches or force a (re)configuration. Signed-off-by: Jerome Brunet Tested-by: Neil Armstrong Tested-by: Kevin Hilman Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 81a7a12196ff..a4d6c068b545 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2245,7 +2245,7 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card, dapm_kcontrol_for_each_path(path, kcontrol) { found = 1; /* we now need to match the string in the enum to the path */ - if (!(strcmp(path->name, e->texts[mux]))) + if (e && !(strcmp(path->name, e->texts[mux]))) connect = true; else connect = false; From e35f5ad6a965de5d301ca5957a1c48c53fe366fb Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 15 May 2019 15:18:56 +0200 Subject: [PATCH 036/626] ASoC: meson: add tohdmitx DT bindings Add the bindings and the related documentation for the audio hdmitx control glue of the Amlogic g12a SoC family Signed-off-by: Jerome Brunet Tested-by: Neil Armstrong Tested-by: Kevin Hilman Signed-off-by: Mark Brown --- .../bindings/sound/amlogic,g12a-tohdmitx.txt | 55 +++++++++++++++++++ .../dt-bindings/sound/meson-g12a-tohdmitx.h | 13 +++++ 2 files changed, 68 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt create mode 100644 include/dt-bindings/sound/meson-g12a-tohdmitx.h diff --git a/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt b/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt new file mode 100644 index 000000000000..aa6c35570d31 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt @@ -0,0 +1,55 @@ +* Amlogic HDMI Tx control glue + +Required properties: +- compatible: "amlogic,g12a-tohdmitx" +- reg: physical base address of the controller and length of memory + mapped region. +- #sound-dai-cells: should be 1. + +Example on the S905X2 SoC: + +tohdmitx: audio-controller@744 { + compatible = "amlogic,g12a-tohdmitx"; + reg = <0x0 0x744 0x0 0x4>; + #sound-dai-cells = <1>; +}; + +Example of an 'amlogic,axg-sound-card': + +sound { + compatible = "amlogic,axg-sound-card"; + +[...] + + dai-link-x { + sound-dai = <&tdmif_a>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-0 = <1 1>; + + codec-0 { + sound-dai = <&tohdmitx TOHDMITX_I2S_IN_A>; + }; + + codec-1 { + sound-dai = <&external_dac>; + }; + }; + + dai-link-y { + sound-dai = <&tdmif_c>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-0 = <1 1>; + + codec { + sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>; + }; + }; + + dai-link-z { + sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; + + codec { + sound-dai = <&hdmi_tx>; + }; + }; +}; diff --git a/include/dt-bindings/sound/meson-g12a-tohdmitx.h b/include/dt-bindings/sound/meson-g12a-tohdmitx.h new file mode 100644 index 000000000000..c5e1f48d30d0 --- /dev/null +++ b/include/dt-bindings/sound/meson-g12a-tohdmitx.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DT_MESON_G12A_TOHDMITX_H +#define __DT_MESON_G12A_TOHDMITX_H + +#define TOHDMITX_I2S_IN_A 0 +#define TOHDMITX_I2S_IN_B 1 +#define TOHDMITX_I2S_IN_C 2 +#define TOHDMITX_I2S_OUT 3 +#define TOHDMITX_SPDIF_IN_A 4 +#define TOHDMITX_SPDIF_IN_B 5 +#define TOHDMITX_SPDIF_OUT 6 + +#endif /* __DT_MESON_G12A_TOHDMITX_H */ From 0a8f1117a6803398d361e7bd76fef59c636f143b Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 15 May 2019 15:18:57 +0200 Subject: [PATCH 037/626] ASoC: meson: axg-card: add basic codec-to-codec link support Add basic support for codec-to-codec link in the axg sound card. The cpu side of these links is expected to properly set the hw_params and format of the link. ATM, only the tohdmitx glue is supported but others (like the internal DAC glue) should follow. Signed-off-by: Jerome Brunet Tested-by: Neil Armstrong Tested-by: Kevin Hilman Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 5c8deee8d512..db0a7fc18928 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -29,6 +29,18 @@ struct axg_dai_link_tdm_data { struct axg_dai_link_tdm_mask *codec_masks; }; +/* + * Base params for the codec to codec links + * Those will be over-written by the CPU side of the link + */ +static const struct snd_soc_pcm_stream codec_params = { + .formats = SNDRV_PCM_FMTBIT_S24_LE, + .rate_min = 5525, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 8, +}; + #define PREFIX "amlogic," static int axg_card_reallocate_links(struct axg_card *priv, @@ -517,6 +529,11 @@ static int axg_card_cpu_is_tdm_iface(struct device_node *np) return of_device_is_compatible(np, PREFIX "axg-tdm-iface"); } +static int axg_card_cpu_is_codec(struct device_node *np) +{ + return of_device_is_compatible(np, PREFIX "g12a-tohdmitx"); +} + static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, int *index) { @@ -540,6 +557,8 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, if (axg_card_cpu_is_tdm_iface(dai_link->cpu_of_node)) ret = axg_card_parse_tdm(card, np, index); + else if (axg_card_cpu_is_codec(dai_link->cpu_of_node)) + dai_link->params = &codec_params; return ret; } From c8609f3870f7078fc7922eb816ed4908a9bd44f3 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 15 May 2019 15:18:58 +0200 Subject: [PATCH 038/626] ASoC: meson: add g12a tohdmitx control Add support for the hdmitx control glue of the Amlogic g12a SoC family. This glue links the 3 TDM and 2 SPDIF output interfaces of the SoC to the related inputs of the Synopsys HDMI controller found in these SoCs. Signed-off-by: Jerome Brunet Tested-by: Neil Armstrong Tested-by: Kevin Hilman Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 8 + sound/soc/meson/Makefile | 2 + sound/soc/meson/g12a-tohdmitx.c | 413 ++++++++++++++++++++++++++++++++ 3 files changed, 423 insertions(+) create mode 100644 sound/soc/meson/g12a-tohdmitx.c diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 8779fe23671d..4e5b4d4f3531 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -56,6 +56,7 @@ config SND_MESON_AXG_SOUND_CARD imply SND_MESON_AXG_SPDIFOUT imply SND_MESON_AXG_SPDIFIN imply SND_MESON_AXG_PDM + imply SND_MESON_G12A_TOHDMITX if DRM_MESON_DW_HDMI help Select Y or M to add support for the AXG SoC sound card @@ -82,4 +83,11 @@ config SND_MESON_AXG_PDM help Select Y or M to add support for PDM input embedded in the Amlogic AXG SoC family + +config SND_MESON_G12A_TOHDMITX + tristate "Amlogic G12A To HDMI TX Control Support" + imply SND_SOC_HDMI_CODEC + help + Select Y or M to add support for HDMI audio on the g12a SoC + family endmenu diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index b45dfb9e2f88..1a8b1470ed84 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -11,6 +11,7 @@ snd-soc-meson-axg-sound-card-objs := axg-card.o snd-soc-meson-axg-spdifin-objs := axg-spdifin.o snd-soc-meson-axg-spdifout-objs := axg-spdifout.o snd-soc-meson-axg-pdm-objs := axg-pdm.o +snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o obj-$(CONFIG_SND_MESON_AXG_FRDDR) += snd-soc-meson-axg-frddr.o @@ -23,3 +24,4 @@ obj-$(CONFIG_SND_MESON_AXG_SOUND_CARD) += snd-soc-meson-axg-sound-card.o obj-$(CONFIG_SND_MESON_AXG_SPDIFIN) += snd-soc-meson-axg-spdifin.o obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o obj-$(CONFIG_SND_MESON_AXG_PDM) += snd-soc-meson-axg-pdm.o +obj-$(CONFIG_SND_MESON_G12A_TOHDMITX) += snd-soc-meson-g12a-tohdmitx.o diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c new file mode 100644 index 000000000000..707ccb192e4c --- /dev/null +++ b/sound/soc/meson/g12a-tohdmitx.c @@ -0,0 +1,413 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2019 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define G12A_TOHDMITX_DRV_NAME "g12a-tohdmitx" + +#define TOHDMITX_CTRL0 0x0 +#define CTRL0_ENABLE_SHIFT 31 +#define CTRL0_I2S_DAT_SEL GENMASK(13, 12) +#define CTRL0_I2S_LRCLK_SEL GENMASK(9, 8) +#define CTRL0_I2S_BLK_CAP_INV BIT(7) +#define CTRL0_I2S_BCLK_O_INV BIT(6) +#define CTRL0_I2S_BCLK_SEL GENMASK(5, 4) +#define CTRL0_SPDIF_CLK_CAP_INV BIT(3) +#define CTRL0_SPDIF_CLK_O_INV BIT(2) +#define CTRL0_SPDIF_SEL BIT(1) +#define CTRL0_SPDIF_CLK_SEL BIT(0) + +struct g12a_tohdmitx_input { + struct snd_pcm_hw_params params; + unsigned int fmt; +}; + +static struct snd_soc_dapm_widget * +g12a_tohdmitx_get_input(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_path *p = NULL; + struct snd_soc_dapm_widget *in; + + snd_soc_dapm_widget_for_each_source_path(w, p) { + if (!p->connect) + continue; + + /* Check that we still are in the same component */ + if (snd_soc_dapm_to_component(w->dapm) != + snd_soc_dapm_to_component(p->source->dapm)) + continue; + + if (p->source->id == snd_soc_dapm_dai_in) + return p->source; + + in = g12a_tohdmitx_get_input(p->source); + if (in) + return in; + } + + return NULL; +} + +static struct g12a_tohdmitx_input * +g12a_tohdmitx_get_input_data(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_widget *in = + g12a_tohdmitx_get_input(w); + struct snd_soc_dai *dai; + + if (WARN_ON(!in)) + return NULL; + + dai = in->priv; + + return dai->playback_dma_data; +} + +static const char * const g12a_tohdmitx_i2s_mux_texts[] = { + "I2S A", "I2S B", "I2S C", +}; + +static SOC_ENUM_SINGLE_EXT_DECL(g12a_tohdmitx_i2s_mux_enum, + g12a_tohdmitx_i2s_mux_texts); + +static int g12a_tohdmitx_get_input_val(struct snd_soc_component *component, + unsigned int mask) +{ + unsigned int val; + + snd_soc_component_read(component, TOHDMITX_CTRL0, &val); + return (val & mask) >> __ffs(mask); +} + +static int g12a_tohdmitx_i2s_mux_get_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + + ucontrol->value.enumerated.item[0] = + g12a_tohdmitx_get_input_val(component, CTRL0_I2S_DAT_SEL); + + return 0; +} + +static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux = ucontrol->value.enumerated.item[0]; + unsigned int val = g12a_tohdmitx_get_input_val(component, + CTRL0_I2S_DAT_SEL); + + /* Force disconnect of the mux while updating */ + if (val != mux) + snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + + snd_soc_component_update_bits(component, TOHDMITX_CTRL0, + CTRL0_I2S_DAT_SEL | + CTRL0_I2S_LRCLK_SEL | + CTRL0_I2S_BCLK_SEL, + FIELD_PREP(CTRL0_I2S_DAT_SEL, mux) | + FIELD_PREP(CTRL0_I2S_LRCLK_SEL, mux) | + FIELD_PREP(CTRL0_I2S_BCLK_SEL, mux)); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); + + return 0; +} + +static const struct snd_kcontrol_new g12a_tohdmitx_i2s_mux = + SOC_DAPM_ENUM_EXT("I2S Source", g12a_tohdmitx_i2s_mux_enum, + g12a_tohdmitx_i2s_mux_get_enum, + g12a_tohdmitx_i2s_mux_put_enum); + +static const char * const g12a_tohdmitx_spdif_mux_texts[] = { + "SPDIF A", "SPDIF B", +}; + +static SOC_ENUM_SINGLE_EXT_DECL(g12a_tohdmitx_spdif_mux_enum, + g12a_tohdmitx_spdif_mux_texts); + +static int g12a_tohdmitx_spdif_mux_get_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + + ucontrol->value.enumerated.item[0] = + g12a_tohdmitx_get_input_val(component, CTRL0_SPDIF_SEL); + + return 0; +} + +static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux = ucontrol->value.enumerated.item[0]; + unsigned int val = g12a_tohdmitx_get_input_val(component, + CTRL0_SPDIF_SEL); + + /* Force disconnect of the mux while updating */ + if (val != mux) + snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + + snd_soc_component_update_bits(component, TOHDMITX_CTRL0, + CTRL0_SPDIF_SEL | + CTRL0_SPDIF_CLK_SEL, + FIELD_PREP(CTRL0_SPDIF_SEL, mux) | + FIELD_PREP(CTRL0_SPDIF_CLK_SEL, mux)); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); + + return 0; +} + +static const struct snd_kcontrol_new g12a_tohdmitx_spdif_mux = + SOC_DAPM_ENUM_EXT("SPDIF Source", g12a_tohdmitx_spdif_mux_enum, + g12a_tohdmitx_spdif_mux_get_enum, + g12a_tohdmitx_spdif_mux_put_enum); + +static const struct snd_kcontrol_new g12a_tohdmitx_out_enable = + SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOHDMITX_CTRL0, + CTRL0_ENABLE_SHIFT, 1, 0); + +static const struct snd_soc_dapm_widget g12a_tohdmitx_widgets[] = { + SND_SOC_DAPM_MUX("I2S SRC", SND_SOC_NOPM, 0, 0, + &g12a_tohdmitx_i2s_mux), + SND_SOC_DAPM_SWITCH("I2S OUT EN", SND_SOC_NOPM, 0, 0, + &g12a_tohdmitx_out_enable), + SND_SOC_DAPM_MUX("SPDIF SRC", SND_SOC_NOPM, 0, 0, + &g12a_tohdmitx_spdif_mux), + SND_SOC_DAPM_SWITCH("SPDIF OUT EN", SND_SOC_NOPM, 0, 0, + &g12a_tohdmitx_out_enable), +}; + +static int g12a_tohdmitx_input_probe(struct snd_soc_dai *dai) +{ + struct g12a_tohdmitx_input *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + dai->playback_dma_data = data; + return 0; +} + +static int g12a_tohdmitx_input_remove(struct snd_soc_dai *dai) +{ + kfree(dai->playback_dma_data); + return 0; +} + +static int g12a_tohdmitx_input_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct g12a_tohdmitx_input *data = dai->playback_dma_data; + + /* Save the stream params for the downstream link */ + memcpy(&data->params, params, sizeof(*params)); + + return 0; +} + +static int g12a_tohdmitx_output_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct g12a_tohdmitx_input *in_data = + g12a_tohdmitx_get_input_data(dai->capture_widget); + + if (!in_data) + return -ENODEV; + + memcpy(params, &in_data->params, sizeof(*params)); + + return 0; +} + +static int g12a_tohdmitx_input_set_fmt(struct snd_soc_dai *dai, + unsigned int fmt) +{ + struct g12a_tohdmitx_input *data = dai->playback_dma_data; + + /* Save the source stream format for the downstream link */ + data->fmt = fmt; + return 0; +} + +static int g12a_tohdmitx_output_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct g12a_tohdmitx_input *in_data = + g12a_tohdmitx_get_input_data(dai->capture_widget); + + if (!in_data) + return -ENODEV; + + if (!in_data->fmt) + return 0; + + return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt); +} + +static const struct snd_soc_dai_ops g12a_tohdmitx_input_ops = { + .hw_params = g12a_tohdmitx_input_hw_params, + .set_fmt = g12a_tohdmitx_input_set_fmt, +}; + +static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = { + .hw_params = g12a_tohdmitx_output_hw_params, + .startup = g12a_tohdmitx_output_startup, +}; + +#define TOHDMITX_SPDIF_FORMATS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE) + +#define TOHDMITX_I2S_FORMATS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define TOHDMITX_STREAM(xname, xsuffix, xfmt, xchmax) \ +{ \ + .stream_name = xname " " xsuffix, \ + .channels_min = 1, \ + .channels_max = (xchmax), \ + .rate_min = 8000, \ + .rate_max = 192000, \ + .formats = (xfmt), \ +} + +#define TOHDMITX_IN(xname, xid, xfmt, xchmax) { \ + .name = xname, \ + .id = (xid), \ + .playback = TOHDMITX_STREAM(xname, "Playback", xfmt, xchmax), \ + .ops = &g12a_tohdmitx_input_ops, \ + .probe = g12a_tohdmitx_input_probe, \ + .remove = g12a_tohdmitx_input_remove, \ +} + +#define TOHDMITX_OUT(xname, xid, xfmt, xchmax) { \ + .name = xname, \ + .id = (xid), \ + .capture = TOHDMITX_STREAM(xname, "Capture", xfmt, xchmax), \ + .ops = &g12a_tohdmitx_output_ops, \ +} + +static struct snd_soc_dai_driver g12a_tohdmitx_dai_drv[] = { + TOHDMITX_IN("I2S IN A", TOHDMITX_I2S_IN_A, + TOHDMITX_I2S_FORMATS, 8), + TOHDMITX_IN("I2S IN B", TOHDMITX_I2S_IN_B, + TOHDMITX_I2S_FORMATS, 8), + TOHDMITX_IN("I2S IN C", TOHDMITX_I2S_IN_C, + TOHDMITX_I2S_FORMATS, 8), + TOHDMITX_OUT("I2S OUT", TOHDMITX_I2S_OUT, + TOHDMITX_I2S_FORMATS, 8), + TOHDMITX_IN("SPDIF IN A", TOHDMITX_SPDIF_IN_A, + TOHDMITX_SPDIF_FORMATS, 2), + TOHDMITX_IN("SPDIF IN B", TOHDMITX_SPDIF_IN_B, + TOHDMITX_SPDIF_FORMATS, 2), + TOHDMITX_OUT("SPDIF OUT", TOHDMITX_SPDIF_OUT, + TOHDMITX_SPDIF_FORMATS, 2), +}; + +static int g12a_tohdmi_component_probe(struct snd_soc_component *c) +{ + /* Initialize the static clock parameters */ + return snd_soc_component_write(c, TOHDMITX_CTRL0, + CTRL0_I2S_BLK_CAP_INV | CTRL0_SPDIF_CLK_CAP_INV); +} + +static const struct snd_soc_dapm_route g12a_tohdmitx_routes[] = { + { "I2S SRC", "I2S A", "I2S IN A Playback" }, + { "I2S SRC", "I2S B", "I2S IN B Playback" }, + { "I2S SRC", "I2S C", "I2S IN C Playback" }, + { "I2S OUT EN", "Switch", "I2S SRC" }, + { "I2S OUT Capture", NULL, "I2S OUT EN" }, + { "SPDIF SRC", "SPDIF A", "SPDIF IN A Playback" }, + { "SPDIF SRC", "SPDIF B", "SPDIF IN B Playback" }, + { "SPDIF OUT EN", "Switch", "SPDIF SRC" }, + { "SPDIF OUT Capture", NULL, "SPDIF OUT EN" }, +}; + +static const struct snd_soc_component_driver g12a_tohdmitx_component_drv = { + .probe = g12a_tohdmi_component_probe, + .dapm_widgets = g12a_tohdmitx_widgets, + .num_dapm_widgets = ARRAY_SIZE(g12a_tohdmitx_widgets), + .dapm_routes = g12a_tohdmitx_routes, + .num_dapm_routes = ARRAY_SIZE(g12a_tohdmitx_routes), + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct regmap_config g12a_tohdmitx_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static const struct of_device_id g12a_tohdmitx_of_match[] = { + { .compatible = "amlogic,g12a-tohdmitx", }, + {} +}; +MODULE_DEVICE_TABLE(of, g12a_tohdmitx_of_match); + +static int g12a_tohdmitx_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + void __iomem *regs; + struct regmap *map; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + map = devm_regmap_init_mmio(dev, regs, &g12a_tohdmitx_regmap_cfg); + if (IS_ERR(map)) { + dev_err(dev, "failed to init regmap: %ld\n", + PTR_ERR(map)); + return PTR_ERR(map); + } + + return devm_snd_soc_register_component(dev, + &g12a_tohdmitx_component_drv, g12a_tohdmitx_dai_drv, + ARRAY_SIZE(g12a_tohdmitx_dai_drv)); +} + +static struct platform_driver g12a_tohdmitx_pdrv = { + .driver = { + .name = G12A_TOHDMITX_DRV_NAME, + .of_match_table = g12a_tohdmitx_of_match, + }, + .probe = g12a_tohdmitx_probe, +}; +module_platform_driver(g12a_tohdmitx_pdrv); + +MODULE_AUTHOR("Jerome Brunet "); +MODULE_DESCRIPTION("Amlogic G12a To HDMI Tx Control Codec Driver"); +MODULE_LICENSE("GPL v2"); From 4aecaa0a82b3142fb2f2862b3f25ecc96dc06d8c Mon Sep 17 00:00:00 2001 From: "S.j. Wang" Date: Wed, 15 May 2019 06:42:22 +0000 Subject: [PATCH 039/626] ASoC: fsl_asrc: replace the process_option table with function When we want to support more sample rate, for example 12kHz/24kHz we need update the process_option table, if we want to support more sample rate next time, the table need to be updated again. which is not flexible. We got a function fsl_asrc_sel_proc to replace the table, which can give the pre-processing and post-processing options according to the sample rate. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 71 +++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 0b937924d2e4..71793d3dc75c 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -26,24 +26,6 @@ #define pair_dbg(fmt, ...) \ dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) -/* Sample rates are aligned with that defined in pcm.h file */ -static const u8 process_option[][12][2] = { - /* 8kHz 11.025kHz 16kHz 22.05kHz 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */ - {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */ - {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */ - {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */ - {{1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */ - {{1, 2}, {1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */ - {{1, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */ - {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */ - {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */ -}; - /* Corresponding to process_option */ static int supported_input_rate[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, @@ -79,6 +61,52 @@ static unsigned char output_clk_map_imx53[] = { static unsigned char *clk_map[2]; +/** + * Select the pre-processing and post-processing options + * Make sure to exclude following unsupported cases before + * calling this function: + * 1) inrate > 8.125 * outrate + * 2) inrate > 16.125 * outrate + * + * inrate: input sample rate + * outrate: output sample rate + * pre_proc: return value for pre-processing option + * post_proc: return value for post-processing option + */ +static void fsl_asrc_sel_proc(int inrate, int outrate, + int *pre_proc, int *post_proc) +{ + bool post_proc_cond2; + bool post_proc_cond0; + + /* select pre_proc between [0, 2] */ + if (inrate * 8 > 33 * outrate) + *pre_proc = 2; + else if (inrate * 8 > 15 * outrate) { + if (inrate > 152000) + *pre_proc = 2; + else + *pre_proc = 1; + } else if (inrate < 76000) + *pre_proc = 0; + else if (inrate > 152000) + *pre_proc = 2; + else + *pre_proc = 1; + + /* Condition for selection of post-processing */ + post_proc_cond2 = (inrate * 15 > outrate * 16 && outrate < 56000) || + (inrate > 56000 && outrate < 56000); + post_proc_cond0 = inrate * 23 < outrate * 8; + + if (post_proc_cond2) + *post_proc = 2; + else if (post_proc_cond0) + *post_proc = 0; + else + *post_proc = 1; +} + /** * Request ASRC pair * @@ -239,6 +267,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) u32 inrate, outrate, indiv, outdiv; u32 clk_index[2], div[2]; int in, out, channels; + int pre_proc, post_proc; struct clk *clk; bool ideal; @@ -377,11 +406,13 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index), ASRCTR_IDR(index) | ASRCTR_USR(index)); + fsl_asrc_sel_proc(inrate, outrate, &pre_proc, &post_proc); + /* Apply configurations for pre- and post-processing */ regmap_update_bits(asrc_priv->regmap, REG_ASRCFG, ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index), - ASRCFG_PREMOD(index, process_option[in][out][0]) | - ASRCFG_POSTMOD(index, process_option[in][out][1])); + ASRCFG_PREMOD(index, pre_proc) | + ASRCFG_POSTMOD(index, post_proc)); return fsl_asrc_set_ideal_ratio(pair, inrate, outrate); } From 506c7f9b0612c46732aa74317f59a28d9477905b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 16 May 2019 09:59:25 +0200 Subject: [PATCH 040/626] dt-bindings: sound: Convert Allwinner SPDIF binding to YAML The Allwinner SoCs feature an SPDIF controller across multiple SoC generations. However, earlier generations were a bit simpler than the subsequent ones, and for example would always have RX and TX capabilities, and no reset lines. In order to express this, let's create two YAML schemas instead of the free form text we had before. Signed-off-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Mark Brown --- .../sound/allwinner,sun4i-a10-spdif.yaml | 101 ++++++++++++++++++ .../bindings/sound/sunxi,sun4i-spdif.txt | 42 -------- 2 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml delete mode 100644 Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml new file mode 100644 index 000000000000..5d72d48e923e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/allwinner,sun4i-a10-spdif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 S/PDIF Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Liam Girdwood + - Mark Brown + - Maxime Ripard + +properties: + "#sound-dai-cells": + const: 0 + + compatible: + oneOf: + - const: allwinner,sun4i-a10-spdif + - const: allwinner,sun6i-a31-spdif + - const: allwinner,sun8i-h3-spdif + - items: + - const: allwinner,sun8i-a83t-spdif + - const: allwinner,sun8i-h3-spdif + - items: + - const: allwinner,sun50i-a64-spdif + - const: allwinner,sun8i-h3-spdif + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + + clock-names: + items: + - const: apb + - const: spdif + + dmas: + items: + - description: RX DMA Channel + - description: TX DMA Channel + + dma-names: + items: + - const: rx + - const: tx + + # Even though it only applies to subschemas under the conditionals, + # not listing them here will trigger a warning because of the + # additionalsProperties set to false. + resets: + maxItems: 1 + +allOf: + - if: + properties: + compatible: + contains: + enum: + - allwinner,sun6i-a31-spdif + - allwinner,sun8i-h3-spdif + + then: + required: + - resets + +required: + - "#sound-dai-cells" + - compatible + - reg + - interrupts + - clocks + - clock-names + - dmas + - dma-names + +additionalProperties: false + +examples: + - | + spdif: spdif@1c21000 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun4i-a10-spdif"; + reg = <0x01c21000 0x40>; + interrupts = <13>; + clocks = <&apb0_gates 1>, <&spdif_clk>; + clock-names = "apb", "spdif"; + dmas = <&dma 0 2>, <&dma 0 2>; + dma-names = "rx", "tx"; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt b/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt deleted file mode 100644 index 0c64a209c2e9..000000000000 --- a/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt +++ /dev/null @@ -1,42 +0,0 @@ -Allwinner Sony/Philips Digital Interface Format (S/PDIF) Controller - -The Allwinner S/PDIF audio block is a transceiver that allows the -processor to receive and transmit digital audio via an coaxial cable or -a fibre cable. -For now only playback is supported. - -Required properties: - - - compatible : should be one of the following: - - "allwinner,sun4i-a10-spdif": for the Allwinner A10 SoC - - "allwinner,sun6i-a31-spdif": for the Allwinner A31 SoC - - "allwinner,sun8i-h3-spdif": for the Allwinner H3 SoC - - - reg : Offset and length of the register set for the device. - - - interrupts : Contains the spdif interrupt. - - - dmas : Generic dma devicetree binding as described in - Documentation/devicetree/bindings/dma/dma.txt. - - - dma-names : Two dmas have to be defined, "tx" and "rx". - - - clocks : Contains an entry for each entry in clock-names. - - - clock-names : Includes the following entries: - "apb" clock for the spdif bus. - "spdif" clock for spdif controller. - - - resets : reset specifier for the ahb reset (A31 and newer only) - -Example: - -spdif: spdif@1c21000 { - compatible = "allwinner,sun4i-a10-spdif"; - reg = <0x01c21000 0x40>; - interrupts = <13>; - clocks = <&apb0_gates 1>, <&spdif_clk>; - clock-names = "apb", "spdif"; - dmas = <&dma 0 2>, <&dma 0 2>; - dma-names = "rx", "tx"; -}; From b1f35dfd7c2f509b0736f1ff02c314130b6b773e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 16 May 2019 09:59:26 +0200 Subject: [PATCH 041/626] dt-bindings: sound: sun4i-spdif: Document that the RX channel can be missing The H3 and compatibles controllers don't have any reception capabilities, even though it was never documented as such in the binding before. Therefore, on those controllers, we don't have the option to set an RX DMA channel. This was already done in the DTSI, but the binding itself was never updated. Let's add a special case in the schemas. Signed-off-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Mark Brown --- .../sound/allwinner,sun4i-a10-spdif.yaml | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml index 5d72d48e923e..a49ef2294a74 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml @@ -44,19 +44,11 @@ properties: - const: apb - const: spdif - dmas: - items: - - description: RX DMA Channel - - description: TX DMA Channel - - dma-names: - items: - - const: rx - - const: tx - # Even though it only applies to subschemas under the conditionals, # not listing them here will trigger a warning because of the # additionalsProperties set to false. + dmas: true + dma-names: true resets: maxItems: 1 @@ -73,6 +65,32 @@ allOf: required: - resets + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-h3-spdif + + then: + properties: + dmas: + description: TX DMA Channel + + dma-names: + const: tx + + else: + properties: + dmas: + items: + - description: RX DMA Channel + - description: TX DMA Channel + + dma-names: + items: + - const: rx + - const: tx + required: - "#sound-dai-cells" - compatible From bfe95dfa4dacefbe20a8532bdac0a19da0708be4 Mon Sep 17 00:00:00 2001 From: "S.j. Wang" Date: Thu, 16 May 2019 06:04:58 +0000 Subject: [PATCH 042/626] ASoC: cs42xx8: Add reset gpio handling Handle the reset GPIO and reset the device every time we start it. Signed-off-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/codecs/cs42xx8.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index ebb9e0cf8364..3e8dbf63adbe 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,7 @@ struct cs42xx8_priv { bool slave_mode; unsigned long sysclk; u32 tx_channels; + struct gpio_desc *gpiod_reset; }; /* -127.5dB to 0dB with step of 0.5dB */ @@ -467,6 +469,13 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap) return -EINVAL; } + cs42xx8->gpiod_reset = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(cs42xx8->gpiod_reset)) + return PTR_ERR(cs42xx8->gpiod_reset); + + gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0); + cs42xx8->clk = devm_clk_get(dev, "mclk"); if (IS_ERR(cs42xx8->clk)) { dev_err(dev, "failed to get the clock: %ld\n", @@ -547,6 +556,8 @@ static int cs42xx8_runtime_resume(struct device *dev) return ret; } + gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0); + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies); if (ret) { @@ -585,6 +596,8 @@ static int cs42xx8_runtime_suspend(struct device *dev) regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies); + gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 1); + clk_disable_unprepare(cs42xx8->clk); return 0; From bfa8130f50a63563eae10ef933fe01b50b3e87a0 Mon Sep 17 00:00:00 2001 From: Saravanan Sekar Date: Sat, 11 May 2019 17:11:49 +0200 Subject: [PATCH 043/626] ASoC: tlv320aic3x: Add support for high power analog output Add support to output level control for the analog high power output drivers HPOUT and HPCOM. Signed-off-by: Saravanan Sekar Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 516d17cb2182..599e4ed3850b 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -324,6 +324,9 @@ static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 50, 0); */ static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1); +/* Output volumes. From 0 to 9 dB in 1 dB steps */ +static const DECLARE_TLV_DB_SCALE(out_tlv, 0, 100, 0); + static const struct snd_kcontrol_new aic3x_snd_controls[] = { /* Output */ SOC_DOUBLE_R_TLV("PCM Playback Volume", @@ -386,11 +389,17 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - /* Output pin mute controls */ + /* Output pin controls */ + SOC_DOUBLE_R_TLV("Line Playback Volume", LLOPM_CTRL, RLOPM_CTRL, 4, + 9, 0, out_tlv), SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, 0x01, 0), + SOC_DOUBLE_R_TLV("HP Playback Volume", HPLOUT_CTRL, HPROUT_CTRL, 4, + 9, 0, out_tlv), SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, 0x01, 0), + SOC_DOUBLE_R_TLV("HPCOM Playback Volume", HPLCOM_CTRL, HPRCOM_CTRL, + 4, 9, 0, out_tlv), SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, 0x01, 0), @@ -472,6 +481,9 @@ static const struct snd_kcontrol_new aic3x_mono_controls[] = { 0, 118, 1, output_stage_tlv), SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), + SOC_SINGLE_TLV("Mono Playback Volume", MONOLOPM_CTRL, 4, 9, 0, + out_tlv), + }; /* From c4580f20971539a78231591852055a375a957fab Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 17 May 2019 11:56:22 +0900 Subject: [PATCH 044/626] ALSA: dice: add stream format parameters for PreSonus FireStudio FireStudio was launched by PreSonus 2009. This model consists of three ICs for its packet processing on IEEE 1394 bus: - Texus Instruments TSB41AB2 for physical layer of IEEE 1394 bus - WaveFront semiconductor, Dice II STD ASIC for link layer of IEEE 1394 bus and protocol layer - Xilinx Spartan XG3S500E FPGA for signal processing This model don't support TCAT extended application protocol. For such devices, ALSA dice driver needs to have hard-coded parameters for stream formats. This commit adds hard-coded table for this model. As a result, sampling transfer frequencies of 88.2/96.0 kHz are supported. I note that this patch can be backported to Linux kernel v4.18 and later. $ python2 crpp < /sys/bus/firewire/devices/fw1/config_rom ROM header and bus information block ----------------------------------------------------------------- 400 04042eda bus_info_length 4, crc_length 4, crc 11994 404 31333934 bus_name "1394" 408 e0ff8112 irmc 1, cmc 1, isc 1, bmc 0, pmc 0, cyc_clk_acc 255, max_rec 8 (512), max_rom 1, gen 1, spd 2 (S400) 40c 000a9204 company_id 000a92 | 410 023a8b7f device_id 04023a8b7f | EUI-64 000a9204023a8b7f root directory ----------------------------------------------------------------- 414 000661b6 directory_length 6, crc 25014 418 03000a92 vendor 41c 8100000a --> descriptor leaf at 444 420 17000008 model 424 8100000d --> descriptor leaf at 458 428 0c0087c0 node capabilities per IEEE 1394 42c d1000001 --> unit directory at 430 unit directory at 430 ----------------------------------------------------------------- 430 00041c75 directory_length 4, crc 7285 434 12000a92 specifier id 438 13000001 version 43c 17000008 model 440 8100000c --> descriptor leaf at 470 descriptor leaf at 444 ----------------------------------------------------------------- 444 00047c11 leaf_length 4, crc 31761 448 00000000 textual descriptor 44c 00000000 minimal ASCII 450 50726553 "PreS" 454 6f6e7573 "onus" descriptor leaf at 458 ----------------------------------------------------------------- 458 0005d7b3 leaf_length 5, crc 55219 45c 00000000 textual descriptor 460 00000000 minimal ASCII 464 46495245 "FIRE" 468 53545544 "STUD" 46c 494f0000 "IO" descriptor leaf at 470 ----------------------------------------------------------------- 470 0005d7b3 leaf_length 5, crc 55219 474 00000000 textual descriptor 478 00000000 minimal ASCII 47c 46495245 "FIRE" 480 53545544 "STUD" 484 494f0000 "IO" Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/Makefile | 2 +- sound/firewire/dice/dice-presonus.c | 62 +++++++++++++++++++++++++++++ sound/firewire/dice/dice.c | 9 +++++ sound/firewire/dice/dice.h | 1 + 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 sound/firewire/dice/dice-presonus.c diff --git a/sound/firewire/dice/Makefile b/sound/firewire/dice/Makefile index 37062a233f6a..7efca3648c6a 100644 --- a/sound/firewire/dice/Makefile +++ b/sound/firewire/dice/Makefile @@ -1,4 +1,4 @@ snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \ dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \ - dice-alesis.o dice-extension.o dice-mytek.o + dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o obj-$(CONFIG_SND_DICE) += snd-dice.o diff --git a/sound/firewire/dice/dice-presonus.c b/sound/firewire/dice/dice-presonus.c new file mode 100644 index 000000000000..503f462a83f4 --- /dev/null +++ b/sound/firewire/dice/dice-presonus.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +// dice-presonus.c - a part of driver for DICE based devices +// +// Copyright (c) 2019 Takashi Sakamoto +// +// Licensed under the terms of the GNU General Public License, version 2. + +#include "dice.h" + +struct dice_presonus_spec { + unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT]; + unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT]; + bool has_midi; +}; + +static const struct dice_presonus_spec dice_presonus_firesutio = { + .tx_pcm_chs = {{16, 16, 0}, {10, 2, 0} }, + .rx_pcm_chs = {{16, 16, 0}, {10, 2, 0} }, + .has_midi = true, +}; + +int snd_dice_detect_presonus_formats(struct snd_dice *dice) +{ + static const struct { + u32 model_id; + const struct dice_presonus_spec *spec; + } *entry, entries[] = { + {0x000008, &dice_presonus_firesutio}, + }; + struct fw_csr_iterator it; + int key, val, model_id; + int i; + + model_id = 0; + fw_csr_iterator_init(&it, dice->unit->directory); + while (fw_csr_iterator_next(&it, &key, &val)) { + if (key == CSR_MODEL) { + model_id = val; + break; + } + } + + for (i = 0; i < ARRAY_SIZE(entries); ++i) { + entry = entries + i; + if (entry->model_id == model_id) + break; + } + if (i == ARRAY_SIZE(entries)) + return -ENODEV; + + memcpy(dice->tx_pcm_chs, entry->spec->tx_pcm_chs, + MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int)); + memcpy(dice->rx_pcm_chs, entry->spec->rx_pcm_chs, + MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int)); + + if (entry->spec->has_midi) { + dice->tx_midi_ports[0] = 1; + dice->rx_midi_ports[0] = 1; + } + + return 0; +} diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index eee184b05d93..ac600e061d7b 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -19,6 +19,7 @@ MODULE_LICENSE("GPL v2"); #define OUI_MAUDIO 0x000d6c #define OUI_MYTEK 0x001ee8 #define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE. +#define OUI_PRESONUS 0x000a92 #define DICE_CATEGORY_ID 0x04 #define WEISS_CATEGORY_ID 0x00 @@ -371,6 +372,14 @@ static const struct ieee1394_device_id dice_id_table[] = { .vendor_id = OUI_SSL, .model_id = 0x000070, }, + // Presonus FireStudio. + { + .match_flags = IEEE1394_MATCH_VENDOR_ID | + IEEE1394_MATCH_MODEL_ID, + .vendor_id = OUI_PRESONUS, + .model_id = 0x000008, + .driver_data = (kernel_ulong_t)snd_dice_detect_presonus_formats, + }, { .match_flags = IEEE1394_MATCH_VERSION, .version = DICE_INTERFACE, diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 83353a3559e8..9699adc2a96d 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -227,5 +227,6 @@ int snd_dice_detect_tcelectronic_formats(struct snd_dice *dice); int snd_dice_detect_alesis_formats(struct snd_dice *dice); int snd_dice_detect_extension_formats(struct snd_dice *dice); int snd_dice_detect_mytek_formats(struct snd_dice *dice); +int snd_dice_detect_presonus_formats(struct snd_dice *dice); #endif From b0a821daf0d04e5a8ae99829e24f2fe538f25763 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Thu, 16 May 2019 13:26:28 +0300 Subject: [PATCH 045/626] ASoC: rename functions that pollute the simple_xxx namespace include/linux/fs.h defines a bunch of simple fs helpers, (e.g. simple_rename) and we intend to add an fs helper named simple_remove. Rename the ASoC driver static functions, so they will not collide with the upcoming fs helper function name. Cc: Kuninori Morimoto Cc: Mark Brown Signed-off-by: Amir Goldstein Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9b568f578bcd..d16e894fce2b 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -607,7 +607,7 @@ static int simple_soc_probe(struct snd_soc_card *card) return 0; } -static int simple_probe(struct platform_device *pdev) +static int asoc_simple_probe(struct platform_device *pdev) { struct asoc_simple_priv *priv; struct device *dev = &pdev->dev; @@ -705,7 +705,7 @@ err: return ret; } -static int simple_remove(struct platform_device *pdev) +static int asoc_simple_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); @@ -726,8 +726,8 @@ static struct platform_driver asoc_simple_card = { .pm = &snd_soc_pm_ops, .of_match_table = simple_of_match, }, - .probe = simple_probe, - .remove = simple_remove, + .probe = asoc_simple_probe, + .remove = asoc_simple_remove, }; module_platform_driver(asoc_simple_card); From 326b18176353d26df54dbc8b4b75ed4332898f61 Mon Sep 17 00:00:00 2001 From: Shunli Wang Date: Mon, 20 May 2019 16:24:20 +0800 Subject: [PATCH 046/626] ASoC: Mediatek: MT8183: enable IIR filter IIR fileter can remove DC offset. It must be enabled when dmic or amic connected to pmic is used. Signed-off-by: Shunli Wang Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-dai-adda.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-adda.c b/sound/soc/mediatek/mt8183/mt8183-dai-adda.c index 017d7d1d9148..2b758a18c2ea 100644 --- a/sound/soc/mediatek/mt8183/mt8183-dai-adda.c +++ b/sound/soc/mediatek/mt8183/mt8183-dai-adda.c @@ -176,9 +176,6 @@ static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ usleep_range(125, 135); - - /* reset dmic */ - afe_priv->mtkaif_dmic = 0; break; default: break; @@ -426,6 +423,17 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); + /* enable iir */ + ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) & + UL_IIR_ON_TMP_CTL_MASK_SFT; + + /* 35Hz @ 48k */ + regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_02_01, 0x00000000); + regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_04_03, 0x00003FB8); + regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_06_05, 0x3FB80000); + regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_08_07, 0x3FB80000); + regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_10_09, 0x0000C048); + regmap_write(afe->regmap, AFE_ADDA_UL_SRC_CON0, ul_src_con0); /* mtkaif_rxif_data_mode = 0, amic */ From 39f2d114a1c7d73d601f19cbea0a955ade2784c3 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Sat, 18 May 2019 13:30:09 -0500 Subject: [PATCH 047/626] ASoC: Intel: glk_rt5682_max98357a: Remap button control-function Assign button functions based on Android wired headset specs(v1.1). Signed-off-by: Yong Zhi Signed-off-by: Naveen Manohar Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/glk_rt5682_max98357a.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index d17126f7757c..6b677b5bcdcd 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -169,9 +169,10 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) jack = &ctx->geminilake_headset; snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + ret = snd_soc_component_set_jack(component, jack, NULL); if (ret) { From e9b5daad4e9bdd1b9e467873a4463c867ccf9ff1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 17 May 2019 10:29:16 +0900 Subject: [PATCH 048/626] ASoC: rsnd: move pcm_new from snd_soc_component_driver to snd_soc_dai_driver snd_soc_dai_driver :: pcm_new has snd_soc_dai as parameter, but snd_soc_component_driver :: pcm_new doesn't have it. rsnd driver needs snd_soc_dai at pcm_new. This patch moves .pcm_new from snd_soc_component_driver to snd_soc_dai_driver, and don't use rtd->cpu_dai anymore. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 120 +++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 37cb61553d5f..56e8dae9a15c 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1176,6 +1176,65 @@ of_node_compatible: return ret; } + +#define PREALLOC_BUFFER (32 * 1024) +#define PREALLOC_BUFFER_MAX (32 * 1024) + +static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd, + struct rsnd_dai_stream *io, + int stream) +{ + struct rsnd_priv *priv = rsnd_io_to_priv(io); + struct device *dev = rsnd_priv_to_dev(priv); + struct snd_pcm_substream *substream; + + /* + * use Audio-DMAC dev if we can use IPMMU + * see + * rsnd_dmaen_attach() + */ + if (io->dmac_dev) + dev = io->dmac_dev; + + for (substream = rtd->pcm->streams[stream].substream; + substream; + substream = substream->next) { + snd_pcm_lib_preallocate_pages(substream, + SNDRV_DMA_TYPE_DEV, + dev, + PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); + } + + return 0; +} + +static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai) +{ + struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); + int ret; + + ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd); + if (ret) + return ret; + + ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd); + if (ret) + return ret; + + ret = rsnd_preallocate_pages(rtd, &rdai->playback, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + return ret; + + ret = rsnd_preallocate_pages(rtd, &rdai->capture, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + return ret; + + return 0; +} + static void __rsnd_dai_probe(struct rsnd_priv *priv, struct device_node *dai_np, int dai_i) @@ -1198,6 +1257,7 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, rdai->priv = priv; drv->name = rdai->name; drv->ops = &rsnd_soc_dai_ops; + drv->pcm_new = rsnd_pcm_new; snprintf(io_playback->name, RSND_DAI_NAME_SIZE, "DAI%d Playback", dai_i); @@ -1572,68 +1632,8 @@ int rsnd_kctrl_new(struct rsnd_mod *mod, /* * snd_soc_component */ - -#define PREALLOC_BUFFER (32 * 1024) -#define PREALLOC_BUFFER_MAX (32 * 1024) - -static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd, - struct rsnd_dai_stream *io, - int stream) -{ - struct rsnd_priv *priv = rsnd_io_to_priv(io); - struct device *dev = rsnd_priv_to_dev(priv); - struct snd_pcm_substream *substream; - - /* - * use Audio-DMAC dev if we can use IPMMU - * see - * rsnd_dmaen_attach() - */ - if (io->dmac_dev) - dev = io->dmac_dev; - - for (substream = rtd->pcm->streams[stream].substream; - substream; - substream = substream->next) { - snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - dev, - PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); - } - - return 0; -} - -static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *dai = rtd->cpu_dai; - struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); - int ret; - - ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd); - if (ret) - return ret; - - ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd); - if (ret) - return ret; - - ret = rsnd_preallocate_pages(rtd, &rdai->playback, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - return ret; - - ret = rsnd_preallocate_pages(rtd, &rdai->capture, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - return ret; - - return 0; -} - static const struct snd_soc_component_driver rsnd_soc_component = { .ops = &rsnd_pcm_ops, - .pcm_new = rsnd_pcm_new, .name = "rsnd", }; From 2ffb0f580bded5f16ec4d619f8abb4745425e864 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 17 May 2019 15:06:37 +0900 Subject: [PATCH 049/626] ASoC: soc-core: WARN() is not related to component->driver->probe soc_probe_component() has WARN() under if (component->driver->probe), but, this WARN() check is not related to .probe callback. So, it should be called at (B) instead of (A). This patch moves it out of if(). if (component->driver->probe) { ret = component->driver->probe(component); ... (A) WARN(...) } (B) WARN(...) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e83edbe27041..ce8c057bcd5b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1420,12 +1420,11 @@ static int soc_probe_component(struct snd_soc_card *card, "ASoC: failed to probe component %d\n", ret); goto err_probe; } - - WARN(dapm->idle_bias_off && - dapm->bias_level != SND_SOC_BIAS_OFF, - "codec %s can not start from non-off bias with idle_bias_off==1\n", - component->name); } + WARN(dapm->idle_bias_off && + dapm->bias_level != SND_SOC_BIAS_OFF, + "codec %s can not start from non-off bias with idle_bias_off==1\n", + component->name); /* machine specific init */ if (component->init) { From 90fdbe8ab27047f7b9da57d1975c14a8d8f39370 Mon Sep 17 00:00:00 2001 From: "S.j. Wang" Date: Thu, 16 May 2019 11:40:56 +0000 Subject: [PATCH 050/626] ASoC: cs42xx8: add reset-gpios in binding document Add reset-gpios property, which is optional. Signed-off-by: Shengjiu Wang Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/cs42xx8.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/cs42xx8.txt b/Documentation/devicetree/bindings/sound/cs42xx8.txt index 8619a156d038..bbfe39347c20 100644 --- a/Documentation/devicetree/bindings/sound/cs42xx8.txt +++ b/Documentation/devicetree/bindings/sound/cs42xx8.txt @@ -14,6 +14,11 @@ Required properties: - VA-supply, VD-supply, VLS-supply, VLC-supply: power supplies for the device, as covered in Documentation/devicetree/bindings/regulator/regulator.txt +Optional properties: + + - reset-gpios : a GPIO spec to define which pin is connected to the chip's + !RESET pin + Example: cs42888: codec@48 { @@ -25,4 +30,5 @@ cs42888: codec@48 { VD-supply = <®_audio>; VLS-supply = <®_audio>; VLC-supply = <®_audio>; + reset-gpios = <&pca9557_b 1 GPIO_ACTIVE_LOW>; }; From 4a10cecc41825becb3283be5e310759f4994f2ea Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 19 May 2019 19:01:05 +0900 Subject: [PATCH 051/626] ALSA: firewire-lib: use the same type of argument for CIP header for tracing event An argument for CIP header in 'in_packet' event is not the same type in 'out_packet' event. This is not good to unify these events. This commit uses the same type of argument for these events. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream-trace.h | 6 +++--- sound/firewire/amdtp-stream.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index ac20acf48fc6..a86a827eab90 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -14,7 +14,7 @@ #include TRACE_EVENT(in_packet, - TP_PROTO(const struct amdtp_stream *s, u32 cycles, u32 *cip_header, unsigned int payload_length, unsigned int index), + TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int index), TP_ARGS(s, cycles, cip_header, payload_length, index), TP_STRUCT__entry( __field(unsigned int, second) @@ -35,8 +35,8 @@ TRACE_EVENT(in_packet, __entry->channel = s->context->channel; __entry->src = fw_parent_device(s->unit)->node_id; __entry->dest = fw_parent_device(s->unit)->card->node_id; - __entry->cip_header0 = cip_header[0]; - __entry->cip_header1 = cip_header[1]; + __entry->cip_header0 = be32_to_cpu(cip_header[0]); + __entry->cip_header1 = be32_to_cpu(cip_header[1]); __entry->payload_quadlets = payload_length / 4; __entry->packet_index = s->packet_index; __entry->irq = !!in_interrupt(); diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 43f28b813386..2614fa551e24 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -555,7 +555,7 @@ static int handle_in_packet(struct amdtp_stream *s, cip_header[0] = be32_to_cpu(buffer[0]); cip_header[1] = be32_to_cpu(buffer[1]); - trace_in_packet(s, cycle, cip_header, payload_length, index); + trace_in_packet(s, cycle, buffer, payload_length, index); /* * This module supports 'Two-quadlet CIP header with SYT field'. From 64d0bf4d4977d18983bce6ad2868c9f75ec3a9f1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 19 May 2019 19:01:06 +0900 Subject: [PATCH 052/626] ALSA: firewire-lib: add data_blocks/data_block_counter parameter to in_packet/out_packet tracing events Tracing events for packets without CIP header have a parameter of data_blocks/data_block_counter, but events for packets with CIP header don't. This is not good to unify these events. This commit adds the missing parameters to the events. In timing to probe 'in_packet' event, data_blocks and data_block_counter are not calculated yet. This commit also changes the timing. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream-trace.h | 24 ++++++++++++++++++------ sound/firewire/amdtp-stream.c | 6 +++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index a86a827eab90..95343fb17583 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -14,8 +14,8 @@ #include TRACE_EVENT(in_packet, - TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int index), - TP_ARGS(s, cycles, cip_header, payload_length, index), + TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int index), + TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, index), TP_STRUCT__entry( __field(unsigned int, second) __field(unsigned int, cycle) @@ -25,6 +25,8 @@ TRACE_EVENT(in_packet, __field(u32, cip_header0) __field(u32, cip_header1) __field(unsigned int, payload_quadlets) + __field(unsigned int, data_blocks) + __field(unsigned int, data_block_counter) __field(unsigned int, packet_index) __field(unsigned int, irq) __field(unsigned int, index) @@ -38,12 +40,14 @@ TRACE_EVENT(in_packet, __entry->cip_header0 = be32_to_cpu(cip_header[0]); __entry->cip_header1 = be32_to_cpu(cip_header[1]); __entry->payload_quadlets = payload_length / 4; + __entry->data_blocks = data_blocks; + __entry->data_block_counter = s->data_block_counter, __entry->packet_index = s->packet_index; __entry->irq = !!in_interrupt(); __entry->index = index; ), TP_printk( - "%02u %04u %04x %04x %02d %08x %08x %03u %02u %01u %02u", + "%02u %04u %04x %04x %02d %08x %08x %03u %02u %03u %02u %01u %02u", __entry->second, __entry->cycle, __entry->src, @@ -52,14 +56,16 @@ TRACE_EVENT(in_packet, __entry->cip_header0, __entry->cip_header1, __entry->payload_quadlets, + __entry->data_blocks, + __entry->data_block_counter, __entry->packet_index, __entry->irq, __entry->index) ); TRACE_EVENT(out_packet, - TP_PROTO(const struct amdtp_stream *s, u32 cycles, __be32 *cip_header, unsigned int payload_length, unsigned int index), - TP_ARGS(s, cycles, cip_header, payload_length, index), + TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int index), + TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, index), TP_STRUCT__entry( __field(unsigned int, second) __field(unsigned int, cycle) @@ -69,6 +75,8 @@ TRACE_EVENT(out_packet, __field(u32, cip_header0) __field(u32, cip_header1) __field(unsigned int, payload_quadlets) + __field(unsigned int, data_blocks) + __field(unsigned int, data_block_counter) __field(unsigned int, packet_index) __field(unsigned int, irq) __field(unsigned int, index) @@ -82,12 +90,14 @@ TRACE_EVENT(out_packet, __entry->cip_header0 = be32_to_cpu(cip_header[0]); __entry->cip_header1 = be32_to_cpu(cip_header[1]); __entry->payload_quadlets = payload_length / 4; + __entry->data_blocks = data_blocks; + __entry->data_block_counter = s->data_block_counter, __entry->packet_index = s->packet_index; __entry->irq = !!in_interrupt(); __entry->index = index; ), TP_printk( - "%02u %04u %04x %04x %02d %08x %08x %03u %02u %01u %02u", + "%02u %04u %04x %04x %02d %08x %08x %03u %02u %03u %02u %01u %02u", __entry->second, __entry->cycle, __entry->src, @@ -96,6 +106,8 @@ TRACE_EVENT(out_packet, __entry->cip_header0, __entry->cip_header1, __entry->payload_quadlets, + __entry->data_blocks, + __entry->data_block_counter, __entry->packet_index, __entry->irq, __entry->index) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 2614fa551e24..67b60490e505 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -493,7 +493,7 @@ static int handle_out_packet(struct amdtp_stream *s, (s->data_block_counter + data_blocks) & 0xff; payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; - trace_out_packet(s, cycle, buffer, payload_length, index); + trace_out_packet(s, cycle, buffer, payload_length, data_blocks, index); if (queue_out_packet(s, payload_length) < 0) return -EIO; @@ -555,8 +555,6 @@ static int handle_in_packet(struct amdtp_stream *s, cip_header[0] = be32_to_cpu(buffer[0]); cip_header[1] = be32_to_cpu(buffer[1]); - trace_in_packet(s, cycle, buffer, payload_length, index); - /* * This module supports 'Two-quadlet CIP header with SYT field'. * For convenience, also check FMT field is AM824 or not. @@ -635,6 +633,8 @@ static int handle_in_packet(struct amdtp_stream *s, return -EIO; } + trace_in_packet(s, cycle, buffer, payload_length, data_blocks, index); + syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK; pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); From a8520f3e9314edddf95479c4796f05b7d594be32 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 19 May 2019 19:01:07 +0900 Subject: [PATCH 053/626] ALSA: firewire-lib: use the same unit for payload argument in tracing events The most of tracing event in this module have the size of payload in byte unit, however 'in_packet_without_header' event have the argument in quadlet unit. This commit change the unit for argument to be consistent. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream-trace.h | 12 ++++++------ sound/firewire/amdtp-stream.c | 6 ++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index 95343fb17583..30c547552cd2 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -39,7 +39,7 @@ TRACE_EVENT(in_packet, __entry->dest = fw_parent_device(s->unit)->card->node_id; __entry->cip_header0 = be32_to_cpu(cip_header[0]); __entry->cip_header1 = be32_to_cpu(cip_header[1]); - __entry->payload_quadlets = payload_length / 4; + __entry->payload_quadlets = payload_length / sizeof(__be32); __entry->data_blocks = data_blocks; __entry->data_block_counter = s->data_block_counter, __entry->packet_index = s->packet_index; @@ -89,7 +89,7 @@ TRACE_EVENT(out_packet, __entry->dest = fw_parent_device(s->unit)->node_id; __entry->cip_header0 = be32_to_cpu(cip_header[0]); __entry->cip_header1 = be32_to_cpu(cip_header[1]); - __entry->payload_quadlets = payload_length / 4; + __entry->payload_quadlets = payload_length / sizeof(__be32); __entry->data_blocks = data_blocks; __entry->data_block_counter = s->data_block_counter, __entry->packet_index = s->packet_index; @@ -114,8 +114,8 @@ TRACE_EVENT(out_packet, ); TRACE_EVENT(in_packet_without_header, - TP_PROTO(const struct amdtp_stream *s, u32 cycles, unsigned int payload_quadlets, unsigned int data_blocks, unsigned int index), - TP_ARGS(s, cycles, payload_quadlets, data_blocks, index), + TP_PROTO(const struct amdtp_stream *s, u32 cycles, unsigned int payload_length, unsigned int data_blocks, unsigned int index), + TP_ARGS(s, cycles, payload_length, data_blocks, index), TP_STRUCT__entry( __field(unsigned int, second) __field(unsigned int, cycle) @@ -135,7 +135,7 @@ TRACE_EVENT(in_packet_without_header, __entry->channel = s->context->channel; __entry->src = fw_parent_device(s->unit)->node_id; __entry->dest = fw_parent_device(s->unit)->card->node_id; - __entry->payload_quadlets = payload_quadlets; + __entry->payload_quadlets = payload_length / sizeof(__be32); __entry->data_blocks = data_blocks, __entry->data_block_counter = s->data_block_counter, __entry->packet_index = s->packet_index; @@ -179,7 +179,7 @@ TRACE_EVENT(out_packet_without_header, __entry->channel = s->context->channel; __entry->src = fw_parent_device(s->unit)->card->node_id; __entry->dest = fw_parent_device(s->unit)->node_id; - __entry->payload_quadlets = payload_length / 4; + __entry->payload_quadlets = payload_length / sizeof(__be32); __entry->data_blocks = data_blocks, __entry->data_block_counter = s->data_block_counter, __entry->packet_index = s->packet_index; diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 67b60490e505..15ae1f2989e5 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -659,16 +659,14 @@ static int handle_in_packet_without_header(struct amdtp_stream *s, unsigned int index) { __be32 *buffer; - unsigned int payload_quadlets; unsigned int data_blocks; struct snd_pcm_substream *pcm; unsigned int pcm_frames; buffer = s->buffer.packets[s->packet_index].buffer; - payload_quadlets = payload_length / 4; - data_blocks = payload_quadlets / s->data_block_quadlets; + data_blocks = payload_length / sizeof(__be32) / s->data_block_quadlets; - trace_in_packet_without_header(s, cycle, payload_quadlets, data_blocks, + trace_in_packet_without_header(s, cycle, payload_length, data_blocks, index); pcm_frames = s->process_data_blocks(s, buffer, data_blocks, NULL); From bde2bbdb307a63e1829c113dba9a378eebe23b18 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 19 May 2019 19:01:08 +0900 Subject: [PATCH 054/626] ALSA: firewire-lib: use dynamic array for CIP header of tracing events This modules handles two types of isochronous packet; one has CIP header in IEC 61883-1/6 and another doesn't. The module also have tracing events corresponding to the types of packet. To unify the events, one event should be probed with or without CIP header. This commit uses dynamic array for the events to be available for the types of packet. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream-trace.h | 36 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index 30c547552cd2..614dfd08aa48 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -22,8 +22,7 @@ TRACE_EVENT(in_packet, __field(int, channel) __field(int, src) __field(int, dest) - __field(u32, cip_header0) - __field(u32, cip_header1) + __dynamic_array(u8, cip_header, cip_header ? 8 : 0) __field(unsigned int, payload_quadlets) __field(unsigned int, data_blocks) __field(unsigned int, data_block_counter) @@ -37,8 +36,10 @@ TRACE_EVENT(in_packet, __entry->channel = s->context->channel; __entry->src = fw_parent_device(s->unit)->node_id; __entry->dest = fw_parent_device(s->unit)->card->node_id; - __entry->cip_header0 = be32_to_cpu(cip_header[0]); - __entry->cip_header1 = be32_to_cpu(cip_header[1]); + if (cip_header) { + memcpy(__get_dynamic_array(cip_header), cip_header, + __get_dynamic_array_len(cip_header)); + } __entry->payload_quadlets = payload_length / sizeof(__be32); __entry->data_blocks = data_blocks; __entry->data_block_counter = s->data_block_counter, @@ -47,20 +48,21 @@ TRACE_EVENT(in_packet, __entry->index = index; ), TP_printk( - "%02u %04u %04x %04x %02d %08x %08x %03u %02u %03u %02u %01u %02u", + "%02u %04u %04x %04x %02d %03u %02u %03u %02u %01u %02u %s", __entry->second, __entry->cycle, __entry->src, __entry->dest, __entry->channel, - __entry->cip_header0, - __entry->cip_header1, __entry->payload_quadlets, __entry->data_blocks, __entry->data_block_counter, __entry->packet_index, __entry->irq, - __entry->index) + __entry->index, + __print_array(__get_dynamic_array(cip_header), + __get_dynamic_array_len(cip_header), + sizeof(u8))) ); TRACE_EVENT(out_packet, @@ -72,8 +74,7 @@ TRACE_EVENT(out_packet, __field(int, channel) __field(int, src) __field(int, dest) - __field(u32, cip_header0) - __field(u32, cip_header1) + __dynamic_array(u8, cip_header, cip_header ? 8 : 0) __field(unsigned int, payload_quadlets) __field(unsigned int, data_blocks) __field(unsigned int, data_block_counter) @@ -87,8 +88,10 @@ TRACE_EVENT(out_packet, __entry->channel = s->context->channel; __entry->src = fw_parent_device(s->unit)->card->node_id; __entry->dest = fw_parent_device(s->unit)->node_id; - __entry->cip_header0 = be32_to_cpu(cip_header[0]); - __entry->cip_header1 = be32_to_cpu(cip_header[1]); + if (cip_header) { + memcpy(__get_dynamic_array(cip_header), cip_header, + __get_dynamic_array_len(cip_header)); + } __entry->payload_quadlets = payload_length / sizeof(__be32); __entry->data_blocks = data_blocks; __entry->data_block_counter = s->data_block_counter, @@ -97,20 +100,21 @@ TRACE_EVENT(out_packet, __entry->index = index; ), TP_printk( - "%02u %04u %04x %04x %02d %08x %08x %03u %02u %03u %02u %01u %02u", + "%02u %04u %04x %04x %02d %03u %02u %03u %02u %01u %02u %s", __entry->second, __entry->cycle, __entry->src, __entry->dest, __entry->channel, - __entry->cip_header0, - __entry->cip_header1, __entry->payload_quadlets, __entry->data_blocks, __entry->data_block_counter, __entry->packet_index, __entry->irq, - __entry->index) + __entry->index, + __print_array(__get_dynamic_array(cip_header), + __get_dynamic_array_len(cip_header), + sizeof(u8))) ); TRACE_EVENT(in_packet_without_header, From 8d3f1fdf521165cac96a21e35f5a1630147d91b1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 19 May 2019 19:01:09 +0900 Subject: [PATCH 055/626] ALSA: firewire-lib: unify tracing events to 'amdtp_packet' event Now four events of this module have the same arguments and probe timing. This commit adds a new event, 'amdtp_packet', and replace them. Filtering functionality of tracing framework is available to pick up events for inbound/outbound isochronous packets. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream-trace.h | 151 ++-------------------------- sound/firewire/amdtp-stream.c | 10 +- 2 files changed, 12 insertions(+), 149 deletions(-) diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index 614dfd08aa48..ab708857979f 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -13,7 +13,7 @@ #include -TRACE_EVENT(in_packet, +TRACE_EVENT(amdtp_packet, TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int index), TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, index), TP_STRUCT__entry( @@ -34,8 +34,13 @@ TRACE_EVENT(in_packet, __entry->second = cycles / CYCLES_PER_SECOND; __entry->cycle = cycles % CYCLES_PER_SECOND; __entry->channel = s->context->channel; - __entry->src = fw_parent_device(s->unit)->node_id; - __entry->dest = fw_parent_device(s->unit)->card->node_id; + if (s->direction == AMDTP_IN_STREAM) { + __entry->src = fw_parent_device(s->unit)->node_id; + __entry->dest = fw_parent_device(s->unit)->card->node_id; + } else { + __entry->src = fw_parent_device(s->unit)->card->node_id; + __entry->dest = fw_parent_device(s->unit)->node_id; + } if (cip_header) { memcpy(__get_dynamic_array(cip_header), cip_header, __get_dynamic_array_len(cip_header)); @@ -65,146 +70,6 @@ TRACE_EVENT(in_packet, sizeof(u8))) ); -TRACE_EVENT(out_packet, - TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int index), - TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, index), - TP_STRUCT__entry( - __field(unsigned int, second) - __field(unsigned int, cycle) - __field(int, channel) - __field(int, src) - __field(int, dest) - __dynamic_array(u8, cip_header, cip_header ? 8 : 0) - __field(unsigned int, payload_quadlets) - __field(unsigned int, data_blocks) - __field(unsigned int, data_block_counter) - __field(unsigned int, packet_index) - __field(unsigned int, irq) - __field(unsigned int, index) - ), - TP_fast_assign( - __entry->second = cycles / CYCLES_PER_SECOND; - __entry->cycle = cycles % CYCLES_PER_SECOND; - __entry->channel = s->context->channel; - __entry->src = fw_parent_device(s->unit)->card->node_id; - __entry->dest = fw_parent_device(s->unit)->node_id; - if (cip_header) { - memcpy(__get_dynamic_array(cip_header), cip_header, - __get_dynamic_array_len(cip_header)); - } - __entry->payload_quadlets = payload_length / sizeof(__be32); - __entry->data_blocks = data_blocks; - __entry->data_block_counter = s->data_block_counter, - __entry->packet_index = s->packet_index; - __entry->irq = !!in_interrupt(); - __entry->index = index; - ), - TP_printk( - "%02u %04u %04x %04x %02d %03u %02u %03u %02u %01u %02u %s", - __entry->second, - __entry->cycle, - __entry->src, - __entry->dest, - __entry->channel, - __entry->payload_quadlets, - __entry->data_blocks, - __entry->data_block_counter, - __entry->packet_index, - __entry->irq, - __entry->index, - __print_array(__get_dynamic_array(cip_header), - __get_dynamic_array_len(cip_header), - sizeof(u8))) -); - -TRACE_EVENT(in_packet_without_header, - TP_PROTO(const struct amdtp_stream *s, u32 cycles, unsigned int payload_length, unsigned int data_blocks, unsigned int index), - TP_ARGS(s, cycles, payload_length, data_blocks, index), - TP_STRUCT__entry( - __field(unsigned int, second) - __field(unsigned int, cycle) - __field(int, channel) - __field(int, src) - __field(int, dest) - __field(unsigned int, payload_quadlets) - __field(unsigned int, data_blocks) - __field(unsigned int, data_block_counter) - __field(unsigned int, packet_index) - __field(unsigned int, irq) - __field(unsigned int, index) - ), - TP_fast_assign( - __entry->second = cycles / CYCLES_PER_SECOND; - __entry->cycle = cycles % CYCLES_PER_SECOND; - __entry->channel = s->context->channel; - __entry->src = fw_parent_device(s->unit)->node_id; - __entry->dest = fw_parent_device(s->unit)->card->node_id; - __entry->payload_quadlets = payload_length / sizeof(__be32); - __entry->data_blocks = data_blocks, - __entry->data_block_counter = s->data_block_counter, - __entry->packet_index = s->packet_index; - __entry->irq = !!in_interrupt(); - __entry->index = index; - ), - TP_printk( - "%02u %04u %04x %04x %02d %03u %02u %03u %02u %01u %02u", - __entry->second, - __entry->cycle, - __entry->src, - __entry->dest, - __entry->channel, - __entry->payload_quadlets, - __entry->data_blocks, - __entry->data_block_counter, - __entry->packet_index, - __entry->irq, - __entry->index) -); - -TRACE_EVENT(out_packet_without_header, - TP_PROTO(const struct amdtp_stream *s, u32 cycles, unsigned int payload_length, unsigned int data_blocks, unsigned int index), - TP_ARGS(s, cycles, payload_length, data_blocks, index), - TP_STRUCT__entry( - __field(unsigned int, second) - __field(unsigned int, cycle) - __field(int, channel) - __field(int, src) - __field(int, dest) - __field(unsigned int, payload_quadlets) - __field(unsigned int, data_blocks) - __field(unsigned int, data_block_counter) - __field(unsigned int, packet_index) - __field(unsigned int, irq) - __field(unsigned int, index) - ), - TP_fast_assign( - __entry->second = cycles / CYCLES_PER_SECOND; - __entry->cycle = cycles % CYCLES_PER_SECOND; - __entry->channel = s->context->channel; - __entry->src = fw_parent_device(s->unit)->card->node_id; - __entry->dest = fw_parent_device(s->unit)->node_id; - __entry->payload_quadlets = payload_length / sizeof(__be32); - __entry->data_blocks = data_blocks, - __entry->data_block_counter = s->data_block_counter, - __entry->packet_index = s->packet_index; - __entry->irq = !!in_interrupt(); - __entry->index = index; - ), - TP_printk( - "%02u %04u %04x %04x %02d %03u %02u %03u %02u %01u %02u", - __entry->second, - __entry->cycle, - __entry->src, - __entry->dest, - __entry->channel, - __entry->payload_quadlets, - __entry->data_blocks, - __entry->data_block_counter, - __entry->packet_index, - __entry->irq, - __entry->index) -); - #endif #undef TRACE_INCLUDE_PATH diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 15ae1f2989e5..6b3f936fab91 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -493,7 +493,7 @@ static int handle_out_packet(struct amdtp_stream *s, (s->data_block_counter + data_blocks) & 0xff; payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; - trace_out_packet(s, cycle, buffer, payload_length, data_blocks, index); + trace_amdtp_packet(s, cycle, buffer, payload_length, data_blocks, index); if (queue_out_packet(s, payload_length) < 0) return -EIO; @@ -524,8 +524,7 @@ static int handle_out_packet_without_header(struct amdtp_stream *s, payload_length = data_blocks * 4 * s->data_block_quadlets; - trace_out_packet_without_header(s, cycle, payload_length, data_blocks, - index); + trace_amdtp_packet(s, cycle, NULL, payload_length, data_blocks, index); if (queue_out_packet(s, payload_length) < 0) return -EIO; @@ -633,7 +632,7 @@ static int handle_in_packet(struct amdtp_stream *s, return -EIO; } - trace_in_packet(s, cycle, buffer, payload_length, data_blocks, index); + trace_amdtp_packet(s, cycle, buffer, payload_length, data_blocks, index); syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK; pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); @@ -666,8 +665,7 @@ static int handle_in_packet_without_header(struct amdtp_stream *s, buffer = s->buffer.packets[s->packet_index].buffer; data_blocks = payload_length / sizeof(__be32) / s->data_block_quadlets; - trace_in_packet_without_header(s, cycle, payload_length, data_blocks, - index); + trace_amdtp_packet(s, cycle, NULL, payload_length, data_blocks, index); pcm_frames = s->process_data_blocks(s, buffer, data_blocks, NULL); s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; From e355d3de196fe08e4de99bc0521c25a36c903b1b Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Tue, 21 May 2019 17:29:37 +0800 Subject: [PATCH 056/626] ASoC: Mediatek: MT8183: fix compile error mtk_regmap_update_bits() has been changed from four parameters to five parameters. Fixes: 1628fc3f4771 ("ASoC: Mediatek: MT8183: add memory interface data align") Signed-off-by: Jiaxin Yu Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-afe-fe-dai.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index 19048c3dc324..d16563408465 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -266,8 +266,7 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, 1, hd_audio, memif->data->hd_shift); mtk_regmap_update_bits(afe->regmap, memif->data->hd_align_reg, - memif->data->hd_align_mshift, - hd_align ? memif->data->hd_align_mshift : 0); + 1, hd_align, memif->data->hd_align_mshift); return 0; } From 383d30e72e682021fdaf0371ade1c58ad2c434a4 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Tue, 21 May 2019 17:29:38 +0800 Subject: [PATCH 057/626] ASoC: Mediatek: MT8183: fix compile error mtk_regmap_update_bits() has been changed to take a shift and warn when reg >= 0 but shift < 0.So the hd_align_mshift must not have shift. Change it from XXX_HD_ALIGN_MASK_SFT to XXX_HD_ALIGN_MASK. Fixes: cf61f5b01531 ("ASoC: Mediatek: MT8183: set data align") Signed-off-by: Jiaxin Yu Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index ab2bce1d9b3d..56c37323bc13 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -439,7 +439,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = DL1_HD_SFT, - .hd_align_mshift = DL1_HD_ALIGN_MASK_SFT, + .hd_align_mshift = DL1_HD_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -460,7 +460,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = DL2_HD_SFT, - .hd_align_mshift = DL2_HD_ALIGN_MASK_SFT, + .hd_align_mshift = DL2_HD_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -481,7 +481,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = DL3_HD_SFT, - .hd_align_mshift = DL3_HD_ALIGN_MASK_SFT, + .hd_align_mshift = DL3_HD_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -502,7 +502,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = VUL2_HD_SFT, - .hd_align_mshift = VUL2_HD_ALIGN_MASK_SFT, + .hd_align_mshift = VUL2_HD_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -523,7 +523,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = AWB_HD_SFT, - .hd_align_mshift = AWB_HD_ALIGN_MASK_SFT, + .hd_align_mshift = AWB_HD_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -544,7 +544,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = AWB2_HD_SFT, - .hd_align_mshift = AWB2_ALIGN_MASK_SFT, + .hd_align_mshift = AWB2_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -565,7 +565,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = VUL12_HD_SFT, - .hd_align_mshift = VUL12_HD_ALIGN_MASK_SFT, + .hd_align_mshift = VUL12_HD_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -586,7 +586,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = MOD_DAI_HD_SFT, - .hd_align_mshift = MOD_DAI_HD_ALIGN_MASK_SFT, + .hd_align_mshift = MOD_DAI_HD_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, @@ -607,7 +607,7 @@ static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { .hd_reg = AFE_MEMIF_HD_MODE, .hd_align_reg = AFE_MEMIF_HDALIGN, .hd_shift = HDMI_HD_SFT, - .hd_align_mshift = HDMI_HD_ALIGN_MASK_SFT, + .hd_align_mshift = HDMI_HD_ALIGN_SFT, .agent_disable_reg = -1, .agent_disable_shift = -1, .msb_reg = -1, From b385256eb54f0193f0f595a675409ba6e7282ffe Mon Sep 17 00:00:00 2001 From: Sathya Prakash M R Date: Mon, 20 May 2019 14:46:43 -0500 Subject: [PATCH 058/626] ASoC: Intel: sof-rt5682: add newline for clarity Make sure quirk handling is cleary split from number of links. Signed-off-by: Sathya Prakash M R Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index f28fb98cc306..fea42e275326 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -519,6 +519,7 @@ static int sof_audio_probe(struct platform_device *pdev) /* compute number of dai links */ sof_audio_card_rt5682.num_links = 1 + dmic_num + hdmi_num; + if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) sof_audio_card_rt5682.num_links++; From 428306c3b3fe107b1d059ceecf6fda09a1fcedf5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 May 2019 10:42:39 +0900 Subject: [PATCH 059/626] ASoC: soc-pcm: fixup try_module_get()/module_put() timing soc_pcm_components_open/close() try to call try_module_get()/module_put() based on component->driver->module_get_upon_open. Here, the purpose why we need to call these functions are to checking module reference. Thus, we need to call try_module_open() even though it doesn't have .open callback. The same reason, we need to call module_put() even though it doesn't have .close This patch calls try_module_get()/module_put() regardless of .open/.close Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 74c7d38af2c6..4a7096a22b28 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -458,10 +458,6 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream, component = rtdcom->component; *last = component; - if (!component->driver->ops || - !component->driver->ops->open) - continue; - if (component->driver->module_get_upon_open && !try_module_get(component->dev->driver->owner)) { dev_err(component->dev, @@ -470,6 +466,10 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream, return -ENODEV; } + if (!component->driver->ops || + !component->driver->ops->open) + continue; + ret = component->driver->ops->open(substream); if (ret < 0) { dev_err(component->dev, @@ -495,11 +495,9 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, if (component == last) break; - if (!component->driver->ops || - !component->driver->ops->close) - continue; - - component->driver->ops->close(substream); + if (component->driver->ops && + component->driver->ops->close) + component->driver->ops->close(substream); if (component->driver->module_get_upon_open) module_put(component->dev->driver->owner); From d281bf5d924a0284f0dac1f471e1d8328b3a92ca Mon Sep 17 00:00:00 2001 From: "S.j. Wang" Date: Wed, 15 May 2019 06:42:26 +0000 Subject: [PATCH 060/626] ASoC: fsl_asrc: Unify the supported input and output rate Unify the supported input and output rate, add the 12kHz/24kHz/128kHz to the support list Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index a8d6710f2541..cbbf6257f08a 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -27,13 +27,14 @@ dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) /* Corresponding to process_option */ -static int supported_input_rate[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, - 96000, 176400, 192000, +static unsigned int supported_asrc_rate[] = { + 5512, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, + 64000, 88200, 96000, 128000, 176400, 192000, }; -static int supported_asrc_rate[] = { - 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, +static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = { + .count = ARRAY_SIZE(supported_asrc_rate), + .list = supported_asrc_rate, }; /** @@ -293,11 +294,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) ideal = config->inclk == INCLK_NONE; /* Validate input and output sample rates */ - for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++) - if (inrate == supported_input_rate[in]) + for (in = 0; in < ARRAY_SIZE(supported_asrc_rate); in++) + if (inrate == supported_asrc_rate[in]) break; - if (in == ARRAY_SIZE(supported_input_rate)) { + if (in == ARRAY_SIZE(supported_asrc_rate)) { pair_err("unsupported input sample rate: %dHz\n", inrate); return -EINVAL; } @@ -311,7 +312,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) return -EINVAL; } - if ((outrate >= 8000 && outrate <= 30000) && + if ((outrate >= 5512 && outrate <= 30000) && (outrate > 24 * inrate || inrate > 8 * outrate)) { pair_err("exceed supported ratio range [1/24, 8] for \ inrate/outrate: %d/%d\n", inrate, outrate); @@ -486,7 +487,9 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream, snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); - return 0; + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &fsl_asrc_rate_constraints); } static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, @@ -599,7 +602,6 @@ static int fsl_asrc_dai_probe(struct snd_soc_dai *dai) return 0; } -#define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000 #define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S20_3LE) @@ -610,14 +612,18 @@ static struct snd_soc_dai_driver fsl_asrc_dai = { .stream_name = "ASRC-Playback", .channels_min = 1, .channels_max = 10, - .rates = FSL_ASRC_RATES, + .rate_min = 5512, + .rate_max = 192000, + .rates = SNDRV_PCM_RATE_KNOT, .formats = FSL_ASRC_FORMATS, }, .capture = { .stream_name = "ASRC-Capture", .channels_min = 1, .channels_max = 10, - .rates = FSL_ASRC_RATES, + .rate_min = 5512, + .rate_max = 192000, + .rates = SNDRV_PCM_RATE_KNOT, .formats = FSL_ASRC_FORMATS, }, .ops = &fsl_asrc_dai_ops, From d3d10a4a1b1950c2d20714c2511b5f58c99bab81 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 21 May 2019 23:57:34 +0900 Subject: [PATCH 061/626] ALSA: firewire-lib: use union for directional parameters Some parameters of struct amdtp_stream is dependent on direction. This commit uses union for such parameters to distinguish from common parameters. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-am824.c | 2 +- sound/firewire/amdtp-stream.c | 97 ++++++++++++--------- sound/firewire/amdtp-stream.h | 35 +++++--- sound/firewire/digi00x/amdtp-dot.c | 2 +- sound/firewire/fireworks/fireworks_stream.c | 4 +- sound/firewire/motu/amdtp-motu.c | 2 +- sound/firewire/tascam/amdtp-tascam.c | 2 +- 7 files changed, 87 insertions(+), 57 deletions(-) diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index 4210e5c6262e..7019a2143581 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -83,7 +83,7 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate, if (err < 0) return err; - s->fdf = AMDTP_FDF_AM824 | s->sfc; + s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc; p->pcm_channels = pcm_channels; p->midi_ports = midi_ports; diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 6b3f936fab91..6977fbbef755 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -260,11 +260,18 @@ int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate, s->data_block_quadlets = data_block_quadlets; s->syt_interval = amdtp_syt_intervals[sfc]; - /* default buffering in the device */ - s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; - if (s->flags & CIP_BLOCKING) - /* additional buffering needed to adjust for no-data packets */ - s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate; + // default buffering in the device. + if (s->direction == AMDTP_OUT_STREAM) { + s->ctx_data.rx.transfer_delay = + TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; + + if (s->flags & CIP_BLOCKING) { + // additional buffering needed to adjust for no-data + // packets. + s->ctx_data.rx.transfer_delay += + TICKS_PER_SECOND * s->syt_interval / rate; + } + } return 0; } @@ -321,10 +328,10 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s, /* Non-blocking mode. */ } else { if (!cip_sfc_is_base_44100(s->sfc)) { - /* Sample_rate / 8000 is an integer, and precomputed. */ - data_blocks = s->data_block_state; + // Sample_rate / 8000 is an integer, and precomputed. + data_blocks = s->ctx_data.rx.data_block_state; } else { - phase = s->data_block_state; + phase = s->ctx_data.rx.data_block_state; /* * This calculates the number of data blocks per packet so that @@ -343,7 +350,7 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s, data_blocks = 11 * (s->sfc >> 1) + (phase == 0); if (++phase >= (80 >> (s->sfc >> 1))) phase = 0; - s->data_block_state = phase; + s->ctx_data.rx.data_block_state = phase; } } @@ -355,9 +362,10 @@ static unsigned int calculate_syt(struct amdtp_stream *s, { unsigned int syt_offset, phase, index, syt; - if (s->last_syt_offset < TICKS_PER_CYCLE) { + if (s->ctx_data.rx.last_syt_offset < TICKS_PER_CYCLE) { if (!cip_sfc_is_base_44100(s->sfc)) - syt_offset = s->last_syt_offset + s->syt_offset_state; + syt_offset = s->ctx_data.rx.last_syt_offset + + s->ctx_data.rx.syt_offset_state; else { /* * The time, in ticks, of the n'th SYT_INTERVAL sample is: @@ -369,21 +377,21 @@ static unsigned int calculate_syt(struct amdtp_stream *s, * 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ... * This code generates _exactly_ the same sequence. */ - phase = s->syt_offset_state; + phase = s->ctx_data.rx.syt_offset_state; index = phase % 13; - syt_offset = s->last_syt_offset; + syt_offset = s->ctx_data.rx.last_syt_offset; syt_offset += 1386 + ((index && !(index & 3)) || phase == 146); if (++phase >= 147) phase = 0; - s->syt_offset_state = phase; + s->ctx_data.rx.syt_offset_state = phase; } } else - syt_offset = s->last_syt_offset - TICKS_PER_CYCLE; - s->last_syt_offset = syt_offset; + syt_offset = s->ctx_data.rx.last_syt_offset - TICKS_PER_CYCLE; + s->ctx_data.rx.last_syt_offset = syt_offset; if (syt_offset < TICKS_PER_CYCLE) { - syt_offset += s->transfer_delay; + syt_offset += s->ctx_data.rx.transfer_delay; syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; syt += syt_offset % TICKS_PER_CYCLE; @@ -457,7 +465,8 @@ static inline int queue_out_packet(struct amdtp_stream *s, static inline int queue_in_packet(struct amdtp_stream *s) { - return queue_packet(s, IR_HEADER_SIZE, s->max_payload_length); + return queue_packet(s, s->ctx_data.tx.ctx_header_size, + s->ctx_data.tx.max_payload_length); } static int handle_out_packet(struct amdtp_stream *s, @@ -484,9 +493,9 @@ static int handle_out_packet(struct amdtp_stream *s, ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | s->data_block_counter); buffer[1] = cpu_to_be32(CIP_EOH | - ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | - ((s->fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | - (syt & CIP_SYT_MASK)); + ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | + ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | + (syt & CIP_SYT_MASK)); if (!(s->flags & CIP_DBC_IS_END_EVENT)) s->data_block_counter = @@ -610,14 +619,14 @@ static int handle_in_packet(struct amdtp_stream *s, data_block_counter = s->data_block_counter; if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && - data_block_counter == s->tx_first_dbc) || + data_block_counter == s->ctx_data.tx.first_dbc) || s->data_block_counter == UINT_MAX) { lost = false; } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { lost = data_block_counter != s->data_block_counter; } else { - if (data_blocks > 0 && s->tx_dbc_interval > 0) - dbc_interval = s->tx_dbc_interval; + if (data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0) + dbc_interval = s->ctx_data.tx.dbc_interval; else dbc_interval = data_blocks; @@ -740,11 +749,11 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, if (s->packet_index < 0) return; - /* The number of packets in buffer */ - packets = header_length / IR_HEADER_SIZE; + // The number of packets in buffer. + packets = header_length / s->ctx_data.tx.ctx_header_size; /* For buffer-over-run prevention. */ - max_payload_length = s->max_payload_length; + max_payload_length = s->ctx_data.tx.max_payload_length; for (i = 0; i < packets; i++) { u32 iso_header = be32_to_cpu(ctx_header[0]); @@ -765,7 +774,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, if (s->handle_packet(s, payload_length, cycle, i) < 0) break; - ctx_header += IR_HEADER_SIZE / sizeof(__be32); + ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); } /* Queueing error or detecting invalid payload. */ @@ -837,7 +846,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) static const struct { unsigned int data_block; unsigned int syt_offset; - } initial_state[] = { + } *entry, initial_state[] = { [CIP_SFC_32000] = { 4, 3072 }, [CIP_SFC_48000] = { 6, 1024 }, [CIP_SFC_96000] = { 12, 1024 }, @@ -846,7 +855,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) [CIP_SFC_88200] = { 0, 67 }, [CIP_SFC_176400] = { 0, 67 }, }; - unsigned int header_size; + unsigned int ctx_header_size; enum dma_data_direction dir; int type, tag, err; @@ -858,23 +867,26 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) goto err_unlock; } - if (s->direction == AMDTP_IN_STREAM) + if (s->direction == AMDTP_IN_STREAM) { s->data_block_counter = UINT_MAX; - else + } else { + entry = &initial_state[s->sfc]; + s->data_block_counter = 0; - s->data_block_state = initial_state[s->sfc].data_block; - s->syt_offset_state = initial_state[s->sfc].syt_offset; - s->last_syt_offset = TICKS_PER_CYCLE; + s->ctx_data.rx.data_block_state = entry->data_block; + s->ctx_data.rx.syt_offset_state = entry->syt_offset; + s->ctx_data.rx.last_syt_offset = TICKS_PER_CYCLE; + } /* initialize packet buffer */ if (s->direction == AMDTP_IN_STREAM) { dir = DMA_FROM_DEVICE; type = FW_ISO_CONTEXT_RECEIVE; - header_size = IR_HEADER_SIZE; + ctx_header_size = IR_HEADER_SIZE; } else { dir = DMA_TO_DEVICE; type = FW_ISO_CONTEXT_TRANSMIT; - header_size = OUT_PACKET_HEADER_SIZE; + ctx_header_size = OUT_PACKET_HEADER_SIZE; } err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, amdtp_stream_get_max_payload(s), dir); @@ -882,8 +894,8 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) goto err_unlock; s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, - type, channel, speed, header_size, - amdtp_stream_first_callback, s); + type, channel, speed, ctx_header_size, + amdtp_stream_first_callback, s); if (IS_ERR(s->context)) { err = PTR_ERR(s->context); if (err == -EBUSY) @@ -894,8 +906,11 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) amdtp_stream_update(s); - if (s->direction == AMDTP_IN_STREAM) - s->max_payload_length = amdtp_stream_get_max_payload(s); + if (s->direction == AMDTP_IN_STREAM) { + s->ctx_data.tx.max_payload_length = + amdtp_stream_get_max_payload(s); + s->ctx_data.tx.ctx_header_size = ctx_header_size; + } if (s->flags & CIP_NO_HEADER) s->tag = TAG_NO_CIP_HEADER; diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index e45de3eecfe3..1945ef59ab92 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -111,7 +111,31 @@ struct amdtp_stream { int (*handle_packet)(struct amdtp_stream *s, unsigned int payload_quadlets, unsigned int cycle, unsigned int index); - unsigned int max_payload_length; + union { + struct { + unsigned int ctx_header_size; + + // limit for payload of iso packet. + unsigned int max_payload_length; + + // For quirks of CIP headers. + // Fixed interval of dbc between previos/current + // packets. + unsigned int dbc_interval; + // Indicate the value of dbc field in a first packet. + unsigned int first_dbc; + } tx; + struct { + // To calculate CIP data blocks and tstamp. + unsigned int transfer_delay; + unsigned int data_block_state; + unsigned int last_syt_offset; + unsigned int syt_offset_state; + + // To generate CIP header. + unsigned int fdf; + } rx; + } ctx_data; /* For CIP headers. */ unsigned int source_node_id_field; @@ -119,19 +143,10 @@ struct amdtp_stream { unsigned int data_block_counter; unsigned int sph; unsigned int fmt; - unsigned int fdf; - /* quirk: fixed interval of dbc between previos/current packets. */ - unsigned int tx_dbc_interval; - /* quirk: indicate the value of dbc field in a first packet. */ - unsigned int tx_first_dbc; /* Internal flags. */ enum cip_sfc sfc; unsigned int syt_interval; - unsigned int transfer_delay; - unsigned int data_block_state; - unsigned int last_syt_offset; - unsigned int syt_offset_state; /* For a PCM substream processing. */ struct snd_pcm_substream *pcm; diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index 4a884a335248..3fb1997dca30 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c @@ -128,7 +128,7 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, if (err < 0) return err; - s->fdf = AMDTP_FDF_AM824 | s->sfc; + s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc; p->pcm_channels = pcm_channels; diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 827161bc269c..74e122e6e68a 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -165,13 +165,13 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw) (efw->firmware_version == 0x5070000 || efw->firmware_version == 0x5070300 || efw->firmware_version == 0x5080000)) - efw->tx_stream.tx_first_dbc = 0x02; + efw->tx_stream.ctx_data.tx.first_dbc = 0x02; /* AudioFire9 always reports wrong dbs. */ if (efw->is_af9) efw->tx_stream.flags |= CIP_WRONG_DBS; /* Firmware version 5.5 reports fixed interval for dbc. */ if (efw->firmware_version == 0x5050000) - efw->tx_stream.tx_dbc_interval = 8; + efw->tx_stream.ctx_data.tx.dbc_interval = 8; err = init_stream(efw, &efw->rx_stream); if (err < 0) { diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index cb0c967dea63..62685f2528ce 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -429,7 +429,7 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, return err; s->sph = 1; - s->fdf = MOTU_FDF_AM824; + s->ctx_data.rx.fdf = MOTU_FDF_AM824; return 0; } diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index a52d1f76c610..1cf0f9470449 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -224,7 +224,7 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, return 0; /* Use fixed value for FDF field. */ - s->fdf = 0x00; + s->ctx_data.rx.fdf = 0x00; /* This protocol uses fixed number of data channels for PCM samples. */ p = s->protocol; From fce9b013fee94ded75624edebf28c8f3506b16cc Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 21 May 2019 23:57:35 +0900 Subject: [PATCH 062/626] ALSA: firewire-lib: add helper function to cancel context inner callback handler In callback handler of isochronous context for both direction, there're common codes to cancel context. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 6977fbbef755..ce39cb92a11e 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -707,6 +707,14 @@ static inline u32 increment_cycle_count(u32 cycle, unsigned int addend) return cycle; } +static inline void cancel_stream(struct amdtp_stream *s) +{ + s->packet_index = -1; + if (in_interrupt()) + amdtp_stream_pcm_abort(s); + WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); +} + static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, void *header, void *private_data) @@ -726,10 +734,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; ++i) { cycle = increment_cycle_count(cycle, 1); if (s->handle_packet(s, 0, cycle, i) < 0) { - s->packet_index = -1; - if (in_interrupt()) - amdtp_stream_pcm_abort(s); - WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); + cancel_stream(s); return; } } @@ -779,10 +784,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, /* Queueing error or detecting invalid payload. */ if (i < packets) { - s->packet_index = -1; - if (in_interrupt()) - amdtp_stream_pcm_abort(s); - WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); + cancel_stream(s); return; } From df9160b9149912a8b23b3a846313656d66cfacb8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 21 May 2019 23:57:36 +0900 Subject: [PATCH 063/626] ALSA: firewire-lib: obsolete macro for header of IT context The header size parameter of 1394 OHCI IT context has no effect. Besides the header size of queued packet is different from context header. This commit cleans codes relevant to these two headers. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index ce39cb92a11e..5ebdac2086c0 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -57,7 +57,6 @@ #define QUEUE_LENGTH 48 #define IR_HEADER_SIZE 8 // For header and timestamp. -#define OUT_PACKET_HEADER_SIZE 0 #define HEADER_TSTAMP_MASK 0x0000ffff static void pcm_period_tasklet(unsigned long data); @@ -428,8 +427,7 @@ static void pcm_period_tasklet(unsigned long data) snd_pcm_period_elapsed(pcm); } -static int queue_packet(struct amdtp_stream *s, unsigned int header_length, - unsigned int payload_length) +static int queue_packet(struct amdtp_stream *s, unsigned int payload_length) { struct fw_iso_packet p = {0}; int err = 0; @@ -439,7 +437,15 @@ static int queue_packet(struct amdtp_stream *s, unsigned int header_length, p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); p.tag = s->tag; - p.header_length = header_length; + + if (s->direction == AMDTP_IN_STREAM) { + // Queue one packet for IR context. + p.header_length = s->ctx_data.tx.ctx_header_size; + } else { + // No header for this packet. + p.header_length = 0; + } + if (payload_length > 0) p.payload_length = payload_length; else @@ -460,13 +466,12 @@ end: static inline int queue_out_packet(struct amdtp_stream *s, unsigned int payload_length) { - return queue_packet(s, OUT_PACKET_HEADER_SIZE, payload_length); + return queue_packet(s, payload_length); } static inline int queue_in_packet(struct amdtp_stream *s) { - return queue_packet(s, s->ctx_data.tx.ctx_header_size, - s->ctx_data.tx.max_payload_length); + return queue_packet(s, s->ctx_data.tx.max_payload_length); } static int handle_out_packet(struct amdtp_stream *s, @@ -888,7 +893,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) } else { dir = DMA_TO_DEVICE; type = FW_ISO_CONTEXT_TRANSMIT; - ctx_header_size = OUT_PACKET_HEADER_SIZE; + ctx_header_size = 0; // No effect for IT context. } err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, amdtp_stream_get_max_payload(s), dir); From 26cd1e5850b70b4ee4a652e5246a356060ea852c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 21 May 2019 23:57:37 +0900 Subject: [PATCH 064/626] ALSA: firewire-lib: use IT context header to compute cycle count for scheduling packet In IT context, header includes information of cycle to have processed queued packet. This commit uses the per-packet information to compute the cycle for packet to be queued, instead of callback argument. In current implementaion of ALSA IEC 61883-1/6 packet streaming engine, 48 packets are queued at first to skip recent cycle. When IT context calls handler, cycle information in header plus 48 cycle means the cycle to be going to queue packet. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 53 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 5ebdac2086c0..f43943fd962d 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -694,13 +694,12 @@ static int handle_in_packet_without_header(struct amdtp_stream *s, return 0; } -/* - * In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On - * the other hand, in DMA descriptors of 1394 OHCI, 3 bits are used to represent - * it. Thus, via Linux firewire subsystem, we can get the 3 bits for second. - */ -static inline u32 compute_cycle_count(u32 tstamp) +// In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On +// the other hand, in DMA descriptors of 1394 OHCI, 3 bits are used to represent +// it. Thus, via Linux firewire subsystem, we can get the 3 bits for second. +static inline u32 compute_cycle_count(__be32 ctx_header_tstamp) { + u32 tstamp = be32_to_cpu(ctx_header_tstamp) & HEADER_TSTAMP_MASK; return (((tstamp >> 13) & 0x07) * 8000) + (tstamp & 0x1fff); } @@ -712,6 +711,16 @@ static inline u32 increment_cycle_count(u32 cycle, unsigned int addend) return cycle; } +// Align to actual cycle count for the packet which is going to be scheduled. +// This module queued the same number of isochronous cycle as QUEUE_LENGTH to +// skip isochronous cycle, therefore it's OK to just increment the cycle by +// QUEUE_LENGTH for scheduled cycle. +static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp) +{ + u32 cycle = compute_cycle_count(ctx_header_tstamp); + return increment_cycle_count(cycle, QUEUE_LENGTH); +} + static inline void cancel_stream(struct amdtp_stream *s) { s->packet_index = -1; @@ -725,23 +734,23 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, void *private_data) { struct amdtp_stream *s = private_data; - unsigned int i, packets = header_length / 4; - u32 cycle; + const __be32 *ctx_header = header; + unsigned int i, packets = header_length / sizeof(*ctx_header); if (s->packet_index < 0) return; - cycle = compute_cycle_count(tstamp); - - /* Align to actual cycle count for the last packet. */ - cycle = increment_cycle_count(cycle, QUEUE_LENGTH - packets); - for (i = 0; i < packets; ++i) { - cycle = increment_cycle_count(cycle, 1); + u32 cycle; + + cycle = compute_it_cycle(*ctx_header); + if (s->handle_packet(s, 0, cycle, i) < 0) { cancel_stream(s); return; } + + ++ctx_header; } fw_iso_context_queue_flush(s->context); @@ -767,10 +776,9 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; i++) { u32 iso_header = be32_to_cpu(ctx_header[0]); - unsigned int cycle; + u32 cycle; - tstamp = be32_to_cpu(ctx_header[1]) & HEADER_TSTAMP_MASK; - cycle = compute_cycle_count(tstamp); + cycle = compute_cycle_count(ctx_header[1]); /* The number of bytes in this packet */ payload_length = iso_header >> ISO_DATA_LENGTH_SHIFT; @@ -802,9 +810,8 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, void *header, void *private_data) { struct amdtp_stream *s = private_data; - __be32 *ctx_header = header; + const __be32 *ctx_header = header; u32 cycle; - unsigned int packets; /* * For in-stream, first packet has come. @@ -814,8 +821,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, wake_up(&s->callback_wait); if (s->direction == AMDTP_IN_STREAM) { - tstamp = be32_to_cpu(ctx_header[1]) & HEADER_TSTAMP_MASK; - cycle = compute_cycle_count(tstamp); + cycle = compute_cycle_count(ctx_header[1]); context->callback.sc = in_stream_callback; if (s->flags & CIP_NO_HEADER) @@ -823,9 +829,8 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, else s->handle_packet = handle_in_packet; } else { - packets = header_length / 4; - cycle = compute_cycle_count(tstamp); - cycle = increment_cycle_count(cycle, QUEUE_LENGTH - packets); + cycle = compute_it_cycle(*ctx_header); + context->callback.sc = out_stream_callback; if (s->flags & CIP_NO_HEADER) s->handle_packet = handle_out_packet_without_header; From a497a4363706b3eb208c64e66e5b485bb3b186ac Mon Sep 17 00:00:00 2001 From: Simon Ho Date: Tue, 21 May 2019 08:26:52 +0200 Subject: [PATCH 065/626] ASoC: Add support for Conexant CX2072X CODEC Initial commit of the Conexant CX2072X CODEC driver. Some features are not present. The CX2072X is a ultra low power stereo audio codec supports I2S/TDM host interface with EQ, DRC features in playback mode. Featues of CX2072X codec: * Two 24 bits DACs and DACs. * Stereo Headphone AMP. * 2.8W per channel class-D output. * Integrated seven bands per channel EQ and DRC. * Fully integrated headset support with detect/switch. * Stereo digital microphone for array applications. * S/PDIF output. * Bi-directional GPIOs. * Support analog and digital PC Beeep. * One headset button support. * Supports a wide variety of host interfaces. -wide variety of I2S and similar bit-stream formats with word lengths of up to 24 bits. -TDM stream supports up to 4 channels. * AEC loopback support. Further fixes by tiwai: * Rebase to 5.2+ * Missing DAPM entry definitions * Missing power hooks * Fix uninitialized variable warning * Rewrite jack detection stuff to use set_jack callback * Plumbing jack detection code for Intel ASoC * Move clk management into runtime PM * Drop incorrect regcache usages * Drop untested stuff: OF table, EQ/DRC handling * Lots of code cleanups and minor refactoring The OF code was dropped due to the lack of testability. It should be easy to re-add once if someone can test it. v1->v2: No change v2->v3: Move register tables to appropriate place Remove some confusing codes Set snd_ctl_boolean_* helpers directly Fix EQ put callback Rename to "DAC1 Switch" from "DAC1 Mute Switch" Drop superfluous regmap calls at shutdown Avoid regmap_register_patch() Add missing register definitions Fix register access on big-endian machine Remove regcache messes v3->v4: Fix the wrong endianess conversion in reg write Minor code cleanups v4->v5: Move clk management to runtime PM Sparse warning fixes Some more code simplification Drop tricky regcache fiddling Apply mutex locks around possible racy sequences Move exported jack detection stuff into set_jack callback v5->v6: Drop buggy&untested EQ and DRC codes Lots of code reduction/cleanup Add more comments about platform-specific stuff Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=115531 Signed-off-by: Simon Ho Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/cx2072x.c | 1727 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cx2072x.h | 314 +++++++ 4 files changed, 2050 insertions(+) create mode 100644 sound/soc/codecs/cx2072x.c create mode 100644 sound/soc/codecs/cx2072x.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 8f577258080b..472bde124ebe 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -72,6 +72,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS47L24 if MFD_CS47L24 select SND_SOC_CS53L30 if I2C select SND_SOC_CX20442 if TTY + select SND_SOC_CX2072X if I2C select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI select SND_SOC_DA7213 if I2C select SND_SOC_DA7218 if I2C @@ -584,6 +585,12 @@ config SND_SOC_CX20442 tristate depends on TTY +config SND_SOC_CX2072X + tristate "Conexant CX2072X CODEC" + depends on I2C + help + Enable support for Conexant CX20721 and CX20723 codec chips. + config SND_SOC_JZ4740_CODEC depends on MIPS || COMPILE_TEST select REGMAP_MMIO diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index aa7720a7a0aa..454b8087a5bd 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -67,6 +67,7 @@ snd-soc-cs4349-objs := cs4349.o snd-soc-cs47l24-objs := cs47l24.o snd-soc-cs53l30-objs := cs53l30.o snd-soc-cx20442-objs := cx20442.o +snd-soc-cx2072x-objs := cx2072x.o snd-soc-da7210-objs := da7210.o snd-soc-da7213-objs := da7213.o snd-soc-da7218-objs := da7218.o @@ -341,6 +342,7 @@ obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o +obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o obj-$(CONFIG_SND_SOC_DA7218) += snd-soc-da7218.o diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c new file mode 100644 index 000000000000..23d2b25fe04c --- /dev/null +++ b/sound/soc/codecs/cx2072x.c @@ -0,0 +1,1727 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// ALSA SoC CX20721/CX20723 codec driver +// +// Copyright: (C) 2017 Conexant Systems, Inc. +// Author: Simon Ho, +// +// TODO: add support for TDM mode. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cx2072x.h" + +#define PLL_OUT_HZ_48 (1024 * 3 * 48000) +#define BITS_PER_SLOT 8 + +/* codec private data */ +struct cx2072x_priv { + struct regmap *regmap; + struct clk *mclk; + unsigned int mclk_rate; + struct device *dev; + struct snd_soc_component *codec; + struct snd_soc_jack_gpio jack_gpio; + struct mutex lock; + unsigned int bclk_ratio; + bool pll_changed; + bool i2spcm_changed; + int sample_size; + int frame_size; + int sample_rate; + unsigned int dai_fmt; + bool en_aec_ref; +}; + +/* + * DAC/ADC Volume + * + * max : 74 : 0 dB + * ( in 1 dB step ) + * min : 0 : -74 dB + */ +static const DECLARE_TLV_DB_SCALE(adc_tlv, -7400, 100, 0); +static const DECLARE_TLV_DB_SCALE(dac_tlv, -7400, 100, 0); +static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 1200, 0); + +struct cx2072x_eq_ctrl { + u8 ch; + u8 band; +}; + +static const DECLARE_TLV_DB_RANGE(hpf_tlv, + 0, 0, TLV_DB_SCALE_ITEM(120, 0, 0), + 1, 63, TLV_DB_SCALE_ITEM(30, 30, 0) +); + +/* Lookup table for PRE_DIV */ +static const struct { + unsigned int mclk; + unsigned int div; +} mclk_pre_div[] = { + { 6144000, 1 }, + { 12288000, 2 }, + { 19200000, 3 }, + { 26000000, 4 }, + { 28224000, 5 }, + { 36864000, 6 }, + { 36864000, 7 }, + { 48000000, 8 }, + { 49152000, 8 }, +}; + +/* + * cx2072x register cache. + */ +static const struct reg_default cx2072x_reg_defaults[] = { + { CX2072X_AFG_POWER_STATE, 0x00000003 }, + { CX2072X_UM_RESPONSE, 0x00000000 }, + { CX2072X_GPIO_DATA, 0x00000000 }, + { CX2072X_GPIO_ENABLE, 0x00000000 }, + { CX2072X_GPIO_DIRECTION, 0x00000000 }, + { CX2072X_GPIO_WAKE, 0x00000000 }, + { CX2072X_GPIO_UM_ENABLE, 0x00000000 }, + { CX2072X_GPIO_STICKY_MASK, 0x00000000 }, + { CX2072X_DAC1_CONVERTER_FORMAT, 0x00000031 }, + { CX2072X_DAC1_AMP_GAIN_RIGHT, 0x0000004a }, + { CX2072X_DAC1_AMP_GAIN_LEFT, 0x0000004a }, + { CX2072X_DAC1_POWER_STATE, 0x00000433 }, + { CX2072X_DAC1_CONVERTER_STREAM_CHANNEL, 0x00000000 }, + { CX2072X_DAC1_EAPD_ENABLE, 0x00000000 }, + { CX2072X_DAC2_CONVERTER_FORMAT, 0x00000031 }, + { CX2072X_DAC2_AMP_GAIN_RIGHT, 0x0000004a }, + { CX2072X_DAC2_AMP_GAIN_LEFT, 0x0000004a }, + { CX2072X_DAC2_POWER_STATE, 0x00000433 }, + { CX2072X_DAC2_CONVERTER_STREAM_CHANNEL, 0x00000000 }, + { CX2072X_ADC1_CONVERTER_FORMAT, 0x00000031 }, + { CX2072X_ADC1_AMP_GAIN_RIGHT_0, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_LEFT_0, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_RIGHT_1, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_LEFT_1, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_RIGHT_2, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_LEFT_2, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_RIGHT_3, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_LEFT_3, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_RIGHT_4, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_LEFT_4, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_RIGHT_5, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_LEFT_5, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_RIGHT_6, 0x0000004a }, + { CX2072X_ADC1_AMP_GAIN_LEFT_6, 0x0000004a }, + { CX2072X_ADC1_CONNECTION_SELECT_CONTROL, 0x00000000 }, + { CX2072X_ADC1_POWER_STATE, 0x00000433 }, + { CX2072X_ADC1_CONVERTER_STREAM_CHANNEL, 0x00000000 }, + { CX2072X_ADC2_CONVERTER_FORMAT, 0x00000031 }, + { CX2072X_ADC2_AMP_GAIN_RIGHT_0, 0x0000004a }, + { CX2072X_ADC2_AMP_GAIN_LEFT_0, 0x0000004a }, + { CX2072X_ADC2_AMP_GAIN_RIGHT_1, 0x0000004a }, + { CX2072X_ADC2_AMP_GAIN_LEFT_1, 0x0000004a }, + { CX2072X_ADC2_AMP_GAIN_RIGHT_2, 0x0000004a }, + { CX2072X_ADC2_AMP_GAIN_LEFT_2, 0x0000004a }, + { CX2072X_ADC2_CONNECTION_SELECT_CONTROL, 0x00000000 }, + { CX2072X_ADC2_POWER_STATE, 0x00000433 }, + { CX2072X_ADC2_CONVERTER_STREAM_CHANNEL, 0x00000000 }, + { CX2072X_PORTA_CONNECTION_SELECT_CTRL, 0x00000000 }, + { CX2072X_PORTA_POWER_STATE, 0x00000433 }, + { CX2072X_PORTA_PIN_CTRL, 0x000000c0 }, + { CX2072X_PORTA_UNSOLICITED_RESPONSE, 0x00000000 }, + { CX2072X_PORTA_PIN_SENSE, 0x00000000 }, + { CX2072X_PORTA_EAPD_BTL, 0x00000002 }, + { CX2072X_PORTB_POWER_STATE, 0x00000433 }, + { CX2072X_PORTB_PIN_CTRL, 0x00000000 }, + { CX2072X_PORTB_UNSOLICITED_RESPONSE, 0x00000000 }, + { CX2072X_PORTB_PIN_SENSE, 0x00000000 }, + { CX2072X_PORTB_EAPD_BTL, 0x00000002 }, + { CX2072X_PORTB_GAIN_RIGHT, 0x00000000 }, + { CX2072X_PORTB_GAIN_LEFT, 0x00000000 }, + { CX2072X_PORTC_POWER_STATE, 0x00000433 }, + { CX2072X_PORTC_PIN_CTRL, 0x00000000 }, + { CX2072X_PORTC_GAIN_RIGHT, 0x00000000 }, + { CX2072X_PORTC_GAIN_LEFT, 0x00000000 }, + { CX2072X_PORTD_POWER_STATE, 0x00000433 }, + { CX2072X_PORTD_PIN_CTRL, 0x00000020 }, + { CX2072X_PORTD_UNSOLICITED_RESPONSE, 0x00000000 }, + { CX2072X_PORTD_PIN_SENSE, 0x00000000 }, + { CX2072X_PORTD_GAIN_RIGHT, 0x00000000 }, + { CX2072X_PORTD_GAIN_LEFT, 0x00000000 }, + { CX2072X_PORTE_CONNECTION_SELECT_CTRL, 0x00000000 }, + { CX2072X_PORTE_POWER_STATE, 0x00000433 }, + { CX2072X_PORTE_PIN_CTRL, 0x00000040 }, + { CX2072X_PORTE_UNSOLICITED_RESPONSE, 0x00000000 }, + { CX2072X_PORTE_PIN_SENSE, 0x00000000 }, + { CX2072X_PORTE_EAPD_BTL, 0x00000002 }, + { CX2072X_PORTE_GAIN_RIGHT, 0x00000000 }, + { CX2072X_PORTE_GAIN_LEFT, 0x00000000 }, + { CX2072X_PORTF_POWER_STATE, 0x00000433 }, + { CX2072X_PORTF_PIN_CTRL, 0x00000000 }, + { CX2072X_PORTF_UNSOLICITED_RESPONSE, 0x00000000 }, + { CX2072X_PORTF_PIN_SENSE, 0x00000000 }, + { CX2072X_PORTF_GAIN_RIGHT, 0x00000000 }, + { CX2072X_PORTF_GAIN_LEFT, 0x00000000 }, + { CX2072X_PORTG_POWER_STATE, 0x00000433 }, + { CX2072X_PORTG_PIN_CTRL, 0x00000040 }, + { CX2072X_PORTG_CONNECTION_SELECT_CTRL, 0x00000000 }, + { CX2072X_PORTG_EAPD_BTL, 0x00000002 }, + { CX2072X_PORTM_POWER_STATE, 0x00000433 }, + { CX2072X_PORTM_PIN_CTRL, 0x00000000 }, + { CX2072X_PORTM_CONNECTION_SELECT_CTRL, 0x00000000 }, + { CX2072X_PORTM_EAPD_BTL, 0x00000002 }, + { CX2072X_MIXER_POWER_STATE, 0x00000433 }, + { CX2072X_MIXER_GAIN_RIGHT_0, 0x0000004a }, + { CX2072X_MIXER_GAIN_LEFT_0, 0x0000004a }, + { CX2072X_MIXER_GAIN_RIGHT_1, 0x0000004a }, + { CX2072X_MIXER_GAIN_LEFT_1, 0x0000004a }, + { CX2072X_SPKR_DRC_ENABLE_STEP, 0x040065a4 }, + { CX2072X_SPKR_DRC_CONTROL, 0x007b0024 }, + { CX2072X_SPKR_DRC_TEST, 0x00000000 }, + { CX2072X_DIGITAL_BIOS_TEST0, 0x001f008a }, + { CX2072X_DIGITAL_BIOS_TEST2, 0x00990026 }, + { CX2072X_I2SPCM_CONTROL1, 0x00010001 }, + { CX2072X_I2SPCM_CONTROL2, 0x00000000 }, + { CX2072X_I2SPCM_CONTROL3, 0x00000000 }, + { CX2072X_I2SPCM_CONTROL4, 0x00000000 }, + { CX2072X_I2SPCM_CONTROL5, 0x00000000 }, + { CX2072X_I2SPCM_CONTROL6, 0x00000000 }, + { CX2072X_UM_INTERRUPT_CRTL_E, 0x00000000 }, + { CX2072X_CODEC_TEST2, 0x00000000 }, + { CX2072X_CODEC_TEST9, 0x00000004 }, + { CX2072X_CODEC_TEST20, 0x00000600 }, + { CX2072X_CODEC_TEST26, 0x00000208 }, + { CX2072X_ANALOG_TEST4, 0x00000000 }, + { CX2072X_ANALOG_TEST5, 0x00000000 }, + { CX2072X_ANALOG_TEST6, 0x0000059a }, + { CX2072X_ANALOG_TEST7, 0x000000a7 }, + { CX2072X_ANALOG_TEST8, 0x00000017 }, + { CX2072X_ANALOG_TEST9, 0x00000000 }, + { CX2072X_ANALOG_TEST10, 0x00000285 }, + { CX2072X_ANALOG_TEST11, 0x00000000 }, + { CX2072X_ANALOG_TEST12, 0x00000000 }, + { CX2072X_ANALOG_TEST13, 0x00000000 }, + { CX2072X_DIGITAL_TEST1, 0x00000242 }, + { CX2072X_DIGITAL_TEST11, 0x00000000 }, + { CX2072X_DIGITAL_TEST12, 0x00000084 }, + { CX2072X_DIGITAL_TEST15, 0x00000077 }, + { CX2072X_DIGITAL_TEST16, 0x00000021 }, + { CX2072X_DIGITAL_TEST17, 0x00000018 }, + { CX2072X_DIGITAL_TEST18, 0x00000024 }, + { CX2072X_DIGITAL_TEST19, 0x00000001 }, + { CX2072X_DIGITAL_TEST20, 0x00000002 }, +}; + +/* + * register initialization + */ +static const struct reg_sequence cx2072x_reg_init[] = { + { CX2072X_ANALOG_TEST9, 0x080 }, /* DC offset Calibration */ + { CX2072X_CODEC_TEST26, 0x65f }, /* Disable the PA */ + { CX2072X_ANALOG_TEST10, 0x289 }, /* Set the speaker output gain */ + { CX2072X_CODEC_TEST20, 0xf05 }, + { CX2072X_CODEC_TESTXX, 0x380 }, + { CX2072X_CODEC_TEST26, 0xb90 }, + { CX2072X_CODEC_TEST9, 0x001 }, /* Enable 30 Hz High pass filter */ + { CX2072X_ANALOG_TEST3, 0x300 }, /* Disable PCBEEP pad */ + { CX2072X_CODEC_TEST24, 0x100 }, /* Disable SnM mode */ + { CX2072X_PORTD_PIN_CTRL, 0x020 }, /* Enable PortD input */ + { CX2072X_GPIO_ENABLE, 0x040 }, /* Enable GPIO7 pin for button */ + { CX2072X_GPIO_UM_ENABLE, 0x040 }, /* Enable UM for GPIO7 */ + { CX2072X_UM_RESPONSE, 0x080 }, /* Enable button response */ + { CX2072X_DIGITAL_TEST12, 0x0c4 }, /* Enable headset button */ + { CX2072X_DIGITAL_TEST0, 0x415 }, /* Power down class-D during idle */ + { CX2072X_I2SPCM_CONTROL2, 0x00f }, /* Enable I2S TX */ + { CX2072X_I2SPCM_CONTROL3, 0x00f }, /* Enable I2S RX */ +}; + +static unsigned int cx2072x_register_size(unsigned int reg) +{ + switch (reg) { + case CX2072X_VENDOR_ID: + case CX2072X_REVISION_ID: + case CX2072X_PORTA_PIN_SENSE: + case CX2072X_PORTB_PIN_SENSE: + case CX2072X_PORTD_PIN_SENSE: + case CX2072X_PORTE_PIN_SENSE: + case CX2072X_PORTF_PIN_SENSE: + case CX2072X_I2SPCM_CONTROL1: + case CX2072X_I2SPCM_CONTROL2: + case CX2072X_I2SPCM_CONTROL3: + case CX2072X_I2SPCM_CONTROL4: + case CX2072X_I2SPCM_CONTROL5: + case CX2072X_I2SPCM_CONTROL6: + case CX2072X_UM_INTERRUPT_CRTL_E: + case CX2072X_EQ_G_COEFF: + case CX2072X_SPKR_DRC_CONTROL: + case CX2072X_SPKR_DRC_TEST: + case CX2072X_DIGITAL_BIOS_TEST0: + case CX2072X_DIGITAL_BIOS_TEST2: + return 4; + case CX2072X_EQ_ENABLE_BYPASS: + case CX2072X_EQ_B0_COEFF: + case CX2072X_EQ_B1_COEFF: + case CX2072X_EQ_B2_COEFF: + case CX2072X_EQ_A1_COEFF: + case CX2072X_EQ_A2_COEFF: + case CX2072X_DAC1_CONVERTER_FORMAT: + case CX2072X_DAC2_CONVERTER_FORMAT: + case CX2072X_ADC1_CONVERTER_FORMAT: + case CX2072X_ADC2_CONVERTER_FORMAT: + case CX2072X_CODEC_TEST2: + case CX2072X_CODEC_TEST9: + case CX2072X_CODEC_TEST20: + case CX2072X_CODEC_TEST26: + case CX2072X_ANALOG_TEST3: + case CX2072X_ANALOG_TEST4: + case CX2072X_ANALOG_TEST5: + case CX2072X_ANALOG_TEST6: + case CX2072X_ANALOG_TEST7: + case CX2072X_ANALOG_TEST8: + case CX2072X_ANALOG_TEST9: + case CX2072X_ANALOG_TEST10: + case CX2072X_ANALOG_TEST11: + case CX2072X_ANALOG_TEST12: + case CX2072X_ANALOG_TEST13: + case CX2072X_DIGITAL_TEST0: + case CX2072X_DIGITAL_TEST1: + case CX2072X_DIGITAL_TEST11: + case CX2072X_DIGITAL_TEST12: + case CX2072X_DIGITAL_TEST15: + case CX2072X_DIGITAL_TEST16: + case CX2072X_DIGITAL_TEST17: + case CX2072X_DIGITAL_TEST18: + case CX2072X_DIGITAL_TEST19: + case CX2072X_DIGITAL_TEST20: + return 2; + default: + return 1; + } +} + +static bool cx2072x_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CX2072X_VENDOR_ID: + case CX2072X_REVISION_ID: + case CX2072X_CURRENT_BCLK_FREQUENCY: + case CX2072X_AFG_POWER_STATE: + case CX2072X_UM_RESPONSE: + case CX2072X_GPIO_DATA: + case CX2072X_GPIO_ENABLE: + case CX2072X_GPIO_DIRECTION: + case CX2072X_GPIO_WAKE: + case CX2072X_GPIO_UM_ENABLE: + case CX2072X_GPIO_STICKY_MASK: + case CX2072X_DAC1_CONVERTER_FORMAT: + case CX2072X_DAC1_AMP_GAIN_RIGHT: + case CX2072X_DAC1_AMP_GAIN_LEFT: + case CX2072X_DAC1_POWER_STATE: + case CX2072X_DAC1_CONVERTER_STREAM_CHANNEL: + case CX2072X_DAC1_EAPD_ENABLE: + case CX2072X_DAC2_CONVERTER_FORMAT: + case CX2072X_DAC2_AMP_GAIN_RIGHT: + case CX2072X_DAC2_AMP_GAIN_LEFT: + case CX2072X_DAC2_POWER_STATE: + case CX2072X_DAC2_CONVERTER_STREAM_CHANNEL: + case CX2072X_ADC1_CONVERTER_FORMAT: + case CX2072X_ADC1_AMP_GAIN_RIGHT_0: + case CX2072X_ADC1_AMP_GAIN_LEFT_0: + case CX2072X_ADC1_AMP_GAIN_RIGHT_1: + case CX2072X_ADC1_AMP_GAIN_LEFT_1: + case CX2072X_ADC1_AMP_GAIN_RIGHT_2: + case CX2072X_ADC1_AMP_GAIN_LEFT_2: + case CX2072X_ADC1_AMP_GAIN_RIGHT_3: + case CX2072X_ADC1_AMP_GAIN_LEFT_3: + case CX2072X_ADC1_AMP_GAIN_RIGHT_4: + case CX2072X_ADC1_AMP_GAIN_LEFT_4: + case CX2072X_ADC1_AMP_GAIN_RIGHT_5: + case CX2072X_ADC1_AMP_GAIN_LEFT_5: + case CX2072X_ADC1_AMP_GAIN_RIGHT_6: + case CX2072X_ADC1_AMP_GAIN_LEFT_6: + case CX2072X_ADC1_CONNECTION_SELECT_CONTROL: + case CX2072X_ADC1_POWER_STATE: + case CX2072X_ADC1_CONVERTER_STREAM_CHANNEL: + case CX2072X_ADC2_CONVERTER_FORMAT: + case CX2072X_ADC2_AMP_GAIN_RIGHT_0: + case CX2072X_ADC2_AMP_GAIN_LEFT_0: + case CX2072X_ADC2_AMP_GAIN_RIGHT_1: + case CX2072X_ADC2_AMP_GAIN_LEFT_1: + case CX2072X_ADC2_AMP_GAIN_RIGHT_2: + case CX2072X_ADC2_AMP_GAIN_LEFT_2: + case CX2072X_ADC2_CONNECTION_SELECT_CONTROL: + case CX2072X_ADC2_POWER_STATE: + case CX2072X_ADC2_CONVERTER_STREAM_CHANNEL: + case CX2072X_PORTA_CONNECTION_SELECT_CTRL: + case CX2072X_PORTA_POWER_STATE: + case CX2072X_PORTA_PIN_CTRL: + case CX2072X_PORTA_UNSOLICITED_RESPONSE: + case CX2072X_PORTA_PIN_SENSE: + case CX2072X_PORTA_EAPD_BTL: + case CX2072X_PORTB_POWER_STATE: + case CX2072X_PORTB_PIN_CTRL: + case CX2072X_PORTB_UNSOLICITED_RESPONSE: + case CX2072X_PORTB_PIN_SENSE: + case CX2072X_PORTB_EAPD_BTL: + case CX2072X_PORTB_GAIN_RIGHT: + case CX2072X_PORTB_GAIN_LEFT: + case CX2072X_PORTC_POWER_STATE: + case CX2072X_PORTC_PIN_CTRL: + case CX2072X_PORTC_GAIN_RIGHT: + case CX2072X_PORTC_GAIN_LEFT: + case CX2072X_PORTD_POWER_STATE: + case CX2072X_PORTD_PIN_CTRL: + case CX2072X_PORTD_UNSOLICITED_RESPONSE: + case CX2072X_PORTD_PIN_SENSE: + case CX2072X_PORTD_GAIN_RIGHT: + case CX2072X_PORTD_GAIN_LEFT: + case CX2072X_PORTE_CONNECTION_SELECT_CTRL: + case CX2072X_PORTE_POWER_STATE: + case CX2072X_PORTE_PIN_CTRL: + case CX2072X_PORTE_UNSOLICITED_RESPONSE: + case CX2072X_PORTE_PIN_SENSE: + case CX2072X_PORTE_EAPD_BTL: + case CX2072X_PORTE_GAIN_RIGHT: + case CX2072X_PORTE_GAIN_LEFT: + case CX2072X_PORTF_POWER_STATE: + case CX2072X_PORTF_PIN_CTRL: + case CX2072X_PORTF_UNSOLICITED_RESPONSE: + case CX2072X_PORTF_PIN_SENSE: + case CX2072X_PORTF_GAIN_RIGHT: + case CX2072X_PORTF_GAIN_LEFT: + case CX2072X_PORTG_POWER_STATE: + case CX2072X_PORTG_PIN_CTRL: + case CX2072X_PORTG_CONNECTION_SELECT_CTRL: + case CX2072X_PORTG_EAPD_BTL: + case CX2072X_PORTM_POWER_STATE: + case CX2072X_PORTM_PIN_CTRL: + case CX2072X_PORTM_CONNECTION_SELECT_CTRL: + case CX2072X_PORTM_EAPD_BTL: + case CX2072X_MIXER_POWER_STATE: + case CX2072X_MIXER_GAIN_RIGHT_0: + case CX2072X_MIXER_GAIN_LEFT_0: + case CX2072X_MIXER_GAIN_RIGHT_1: + case CX2072X_MIXER_GAIN_LEFT_1: + case CX2072X_EQ_ENABLE_BYPASS: + case CX2072X_EQ_B0_COEFF: + case CX2072X_EQ_B1_COEFF: + case CX2072X_EQ_B2_COEFF: + case CX2072X_EQ_A1_COEFF: + case CX2072X_EQ_A2_COEFF: + case CX2072X_EQ_G_COEFF: + case CX2072X_SPKR_DRC_ENABLE_STEP: + case CX2072X_SPKR_DRC_CONTROL: + case CX2072X_SPKR_DRC_TEST: + case CX2072X_DIGITAL_BIOS_TEST0: + case CX2072X_DIGITAL_BIOS_TEST2: + case CX2072X_I2SPCM_CONTROL1: + case CX2072X_I2SPCM_CONTROL2: + case CX2072X_I2SPCM_CONTROL3: + case CX2072X_I2SPCM_CONTROL4: + case CX2072X_I2SPCM_CONTROL5: + case CX2072X_I2SPCM_CONTROL6: + case CX2072X_UM_INTERRUPT_CRTL_E: + case CX2072X_CODEC_TEST2: + case CX2072X_CODEC_TEST9: + case CX2072X_CODEC_TEST20: + case CX2072X_CODEC_TEST26: + case CX2072X_ANALOG_TEST4: + case CX2072X_ANALOG_TEST5: + case CX2072X_ANALOG_TEST6: + case CX2072X_ANALOG_TEST7: + case CX2072X_ANALOG_TEST8: + case CX2072X_ANALOG_TEST9: + case CX2072X_ANALOG_TEST10: + case CX2072X_ANALOG_TEST11: + case CX2072X_ANALOG_TEST12: + case CX2072X_ANALOG_TEST13: + case CX2072X_DIGITAL_TEST0: + case CX2072X_DIGITAL_TEST1: + case CX2072X_DIGITAL_TEST11: + case CX2072X_DIGITAL_TEST12: + case CX2072X_DIGITAL_TEST15: + case CX2072X_DIGITAL_TEST16: + case CX2072X_DIGITAL_TEST17: + case CX2072X_DIGITAL_TEST18: + case CX2072X_DIGITAL_TEST19: + case CX2072X_DIGITAL_TEST20: + return true; + default: + return false; + } +} + +static bool cx2072x_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CX2072X_VENDOR_ID: + case CX2072X_REVISION_ID: + case CX2072X_UM_INTERRUPT_CRTL_E: + case CX2072X_DIGITAL_TEST11: + case CX2072X_PORTA_PIN_SENSE: + case CX2072X_PORTB_PIN_SENSE: + case CX2072X_PORTD_PIN_SENSE: + case CX2072X_PORTE_PIN_SENSE: + case CX2072X_PORTF_PIN_SENSE: + case CX2072X_EQ_G_COEFF: + case CX2072X_EQ_BAND: + return true; + default: + return false; + } +} + +static int cx2072x_reg_raw_write(struct i2c_client *client, + unsigned int reg, + const void *val, size_t val_count) +{ + struct device *dev = &client->dev; + u8 buf[2 + CX2072X_MAX_EQ_COEFF]; + int ret; + + if (WARN_ON(val_count + 2 > sizeof(buf))) + return -EINVAL; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + + memcpy(buf + 2, val, val_count); + + ret = i2c_master_send(client, buf, val_count + 2); + if (ret != val_count + 2) { + dev_err(dev, "I2C write failed, ret = %d\n", ret); + return ret < 0 ? ret : -EIO; + } + return 0; +} + +static int cx2072x_reg_write(void *context, unsigned int reg, + unsigned int value) +{ + __le32 raw_value; + unsigned int size; + + size = cx2072x_register_size(reg); + + if (reg == CX2072X_UM_INTERRUPT_CRTL_E) { + /* Update the MSB byte only */ + reg += 3; + size = 1; + value >>= 24; + } + + raw_value = cpu_to_le32(value); + return cx2072x_reg_raw_write(context, reg, &raw_value, size); +} + +static int cx2072x_reg_read(void *context, unsigned int reg, + unsigned int *value) +{ + struct i2c_client *client = context; + struct device *dev = &client->dev; + __le32 recv_buf = 0; + struct i2c_msg msgs[2]; + unsigned int size; + u8 send_buf[2]; + int ret; + + size = cx2072x_register_size(reg); + + send_buf[0] = reg >> 8; + send_buf[1] = reg & 0xff; + + msgs[0].addr = client->addr; + msgs[0].len = sizeof(send_buf); + msgs[0].buf = send_buf; + msgs[0].flags = 0; + + msgs[1].addr = client->addr; + msgs[1].len = size; + msgs[1].buf = (u8 *)&recv_buf; + msgs[1].flags = I2C_M_RD; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) { + dev_err(dev, "Failed to read register, ret = %d\n", ret); + return ret < 0 ? ret : -EIO; + } + + *value = le32_to_cpu(recv_buf); + return 0; +} + +/* get suggested pre_div valuce from mclk frequency */ +static unsigned int get_div_from_mclk(unsigned int mclk) +{ + unsigned int div = 8; + int i; + + for (i = 0; i < ARRAY_SIZE(mclk_pre_div); i++) { + if (mclk <= mclk_pre_div[i].mclk) { + div = mclk_pre_div[i].div; + break; + } + } + return div; +} + +static int cx2072x_config_pll(struct cx2072x_priv *cx2072x) +{ + struct device *dev = cx2072x->dev; + unsigned int pre_div; + unsigned int pre_div_val; + unsigned int pll_input; + unsigned int pll_output; + unsigned int int_div; + unsigned int frac_div; + u64 frac_num; + unsigned int frac; + unsigned int sample_rate = cx2072x->sample_rate; + int pt_sample_per_sync = 2; + int pt_clock_per_sample = 96; + + switch (sample_rate) { + case 48000: + case 32000: + case 24000: + case 16000: + break; + + case 96000: + pt_sample_per_sync = 1; + pt_clock_per_sample = 48; + break; + + case 192000: + pt_sample_per_sync = 0; + pt_clock_per_sample = 24; + break; + + default: + dev_err(dev, "Unsupported sample rate %d\n", sample_rate); + return -EINVAL; + } + + /* Configure PLL settings */ + pre_div = get_div_from_mclk(cx2072x->mclk_rate); + pll_input = cx2072x->mclk_rate / pre_div; + pll_output = sample_rate * 3072; + int_div = pll_output / pll_input; + frac_div = pll_output - (int_div * pll_input); + + if (frac_div) { + frac_div *= 1000; + frac_div /= pll_input; + frac_num = ((4000 + frac_div) * ((1 << 20) - 4)); + do_div(frac_num, 7); + frac = ((u32)frac_num + 499) / 1000; + } + pre_div_val = (pre_div - 1) * 2; + + regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST4, + 0x40 | (pre_div_val << 8)); + if (frac_div == 0) { + /* Int mode */ + regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST7, 0x100); + } else { + /* frac mode */ + regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST6, + frac & 0xfff); + regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST7, + (u8)(frac >> 12)); + } + + int_div--; + regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST8, int_div); + + /* configure PLL tracking */ + if (frac_div == 0) { + /* disable PLL tracking */ + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST16, 0x00); + } else { + /* configure and enable PLL tracking */ + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST16, + (pt_sample_per_sync << 4) & 0xf0); + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST17, + pt_clock_per_sample); + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST18, + pt_clock_per_sample * 3 / 2); + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST19, 0x01); + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST20, 0x02); + regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_TEST16, + 0x01, 0x01); + } + + return 0; +} + +static int cx2072x_config_i2spcm(struct cx2072x_priv *cx2072x) +{ + struct device *dev = cx2072x->dev; + unsigned int bclk_rate = 0; + int is_i2s = 0; + int has_one_bit_delay = 0; + int is_right_j = 0; + int is_frame_inv = 0; + int is_bclk_inv = 0; + int pulse_len = 1; + int frame_len = cx2072x->frame_size; + int sample_size = cx2072x->sample_size; + int i2s_right_slot; + int i2s_right_pause_interval = 0; + int i2s_right_pause_pos; + int is_big_endian = 1; + u64 div; + unsigned int mod; + union cx2072x_reg_i2spcm_ctrl_reg1 reg1; + union cx2072x_reg_i2spcm_ctrl_reg2 reg2; + union cx2072x_reg_i2spcm_ctrl_reg3 reg3; + union cx2072x_reg_i2spcm_ctrl_reg4 reg4; + union cx2072x_reg_i2spcm_ctrl_reg5 reg5; + union cx2072x_reg_i2spcm_ctrl_reg6 reg6; + union cx2072x_reg_digital_bios_test2 regdbt2; + const unsigned int fmt = cx2072x->dai_fmt; + + if (frame_len <= 0) { + dev_err(dev, "Incorrect frame len %d\n", frame_len); + return -EINVAL; + } + + if (sample_size <= 0) { + dev_err(dev, "Incorrect sample size %d\n", sample_size); + return -EINVAL; + } + + dev_dbg(dev, "config_i2spcm set_dai_fmt- %08x\n", fmt); + + regdbt2.ulval = 0xac; + + /* set master/slave */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + reg2.r.tx_master = 1; + reg3.r.rx_master = 1; + dev_dbg(dev, "Sets Master mode\n"); + break; + + case SND_SOC_DAIFMT_CBS_CFS: + reg2.r.tx_master = 0; + reg3.r.rx_master = 0; + dev_dbg(dev, "Sets Slave mode\n"); + break; + + default: + dev_err(dev, "Unsupported DAI master mode\n"); + return -EINVAL; + } + + /* set format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + is_i2s = 1; + has_one_bit_delay = 1; + pulse_len = frame_len / 2; + break; + + case SND_SOC_DAIFMT_RIGHT_J: + is_i2s = 1; + is_right_j = 1; + pulse_len = frame_len / 2; + break; + + case SND_SOC_DAIFMT_LEFT_J: + is_i2s = 1; + pulse_len = frame_len / 2; + break; + + default: + dev_err(dev, "Unsupported DAI format\n"); + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + is_frame_inv = is_i2s; + is_bclk_inv = is_i2s; + break; + + case SND_SOC_DAIFMT_IB_IF: + is_frame_inv = !is_i2s; + is_bclk_inv = !is_i2s; + break; + + case SND_SOC_DAIFMT_IB_NF: + is_frame_inv = is_i2s; + is_bclk_inv = !is_i2s; + break; + + case SND_SOC_DAIFMT_NB_IF: + is_frame_inv = !is_i2s; + is_bclk_inv = is_i2s; + break; + + default: + dev_err(dev, "Unsupported DAI clock inversion\n"); + return -EINVAL; + } + + reg1.r.rx_data_one_line = 1; + reg1.r.tx_data_one_line = 1; + + if (is_i2s) { + i2s_right_slot = (frame_len / 2) / BITS_PER_SLOT; + i2s_right_pause_interval = (frame_len / 2) % BITS_PER_SLOT; + i2s_right_pause_pos = i2s_right_slot * BITS_PER_SLOT; + } + + reg1.r.rx_ws_pol = is_frame_inv; + reg1.r.rx_ws_wid = pulse_len - 1; + + reg1.r.rx_frm_len = frame_len / BITS_PER_SLOT - 1; + reg1.r.rx_sa_size = (sample_size / BITS_PER_SLOT) - 1; + + reg1.r.tx_ws_pol = reg1.r.rx_ws_pol; + reg1.r.tx_ws_wid = pulse_len - 1; + reg1.r.tx_frm_len = reg1.r.rx_frm_len; + reg1.r.tx_sa_size = reg1.r.rx_sa_size; + + reg2.r.tx_endian_sel = !is_big_endian; + reg2.r.tx_dstart_dly = has_one_bit_delay; + if (cx2072x->en_aec_ref) + reg2.r.tx_dstart_dly = 0; + + reg3.r.rx_endian_sel = !is_big_endian; + reg3.r.rx_dstart_dly = has_one_bit_delay; + + reg4.ulval = 0; + + if (is_i2s) { + reg2.r.tx_slot_1 = 0; + reg2.r.tx_slot_2 = i2s_right_slot; + reg3.r.rx_slot_1 = 0; + if (cx2072x->en_aec_ref) + reg3.r.rx_slot_2 = 0; + else + reg3.r.rx_slot_2 = i2s_right_slot; + reg6.r.rx_pause_start_pos = i2s_right_pause_pos; + reg6.r.rx_pause_cycles = i2s_right_pause_interval; + reg6.r.tx_pause_start_pos = i2s_right_pause_pos; + reg6.r.tx_pause_cycles = i2s_right_pause_interval; + } else { + dev_err(dev, "TDM mode is not implemented yet\n"); + return -EINVAL; + } + regdbt2.r.i2s_bclk_invert = is_bclk_inv; + + reg1.r.rx_data_one_line = 1; + reg1.r.tx_data_one_line = 1; + + /* Configures the BCLK output */ + bclk_rate = cx2072x->sample_rate * frame_len; + reg5.r.i2s_pcm_clk_div_chan_en = 0; + + /* Disables bclk output before setting new value */ + regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL5, 0); + + if (reg2.r.tx_master) { + /* Configures BCLK rate */ + div = PLL_OUT_HZ_48; + mod = do_div(div, bclk_rate); + if (mod) { + dev_err(dev, "Unsupported BCLK %dHz\n", bclk_rate); + return -EINVAL; + } + dev_dbg(dev, "enables BCLK %dHz output\n", bclk_rate); + reg5.r.i2s_pcm_clk_div = (u32)div - 1; + reg5.r.i2s_pcm_clk_div_chan_en = 1; + } + + regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL1, reg1.ulval); + regmap_update_bits(cx2072x->regmap, CX2072X_I2SPCM_CONTROL2, 0xffffffc0, + reg2.ulval); + regmap_update_bits(cx2072x->regmap, CX2072X_I2SPCM_CONTROL3, 0xffffffc0, + reg3.ulval); + regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL4, reg4.ulval); + regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL6, reg6.ulval); + regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL5, reg5.ulval); + + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST2, + regdbt2.ulval); + + return 0; +} + +static int afg_power_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm); + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST0, + 0x00, 0x10); + break; + + case SND_SOC_DAPM_PRE_PMD: + regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST0, + 0x10, 0x10); + break; + } + + return 0; +} + +static const struct snd_kcontrol_new cx2072x_snd_controls[] = { + SOC_DOUBLE_R_TLV("PortD Boost Volume", CX2072X_PORTD_GAIN_LEFT, + CX2072X_PORTD_GAIN_RIGHT, 0, 3, 0, boost_tlv), + SOC_DOUBLE_R_TLV("PortC Boost Volume", CX2072X_PORTC_GAIN_LEFT, + CX2072X_PORTC_GAIN_RIGHT, 0, 3, 0, boost_tlv), + SOC_DOUBLE_R_TLV("PortB Boost Volume", CX2072X_PORTB_GAIN_LEFT, + CX2072X_PORTB_GAIN_RIGHT, 0, 3, 0, boost_tlv), + SOC_DOUBLE_R_TLV("PortD ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_1, + CX2072X_ADC1_AMP_GAIN_RIGHT_1, 0, 0x4a, 0, adc_tlv), + SOC_DOUBLE_R_TLV("PortC ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_2, + CX2072X_ADC1_AMP_GAIN_RIGHT_2, 0, 0x4a, 0, adc_tlv), + SOC_DOUBLE_R_TLV("PortB ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_0, + CX2072X_ADC1_AMP_GAIN_RIGHT_0, 0, 0x4a, 0, adc_tlv), + SOC_DOUBLE_R_TLV("DAC1 Volume", CX2072X_DAC1_AMP_GAIN_LEFT, + CX2072X_DAC1_AMP_GAIN_RIGHT, 0, 0x4a, 0, dac_tlv), + SOC_DOUBLE_R("DAC1 Switch", CX2072X_DAC1_AMP_GAIN_LEFT, + CX2072X_DAC1_AMP_GAIN_RIGHT, 7, 1, 0), + SOC_DOUBLE_R_TLV("DAC2 Volume", CX2072X_DAC2_AMP_GAIN_LEFT, + CX2072X_DAC2_AMP_GAIN_RIGHT, 0, 0x4a, 0, dac_tlv), + SOC_SINGLE_TLV("HPF Freq", CX2072X_CODEC_TEST9, 0, 0x3f, 0, hpf_tlv), + SOC_DOUBLE("HPF Switch", CX2072X_CODEC_TEST9, 8, 9, 1, 1), + SOC_SINGLE("PortA HP Amp Switch", CX2072X_PORTA_PIN_CTRL, 7, 1, 0), +}; + +static int cx2072x_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *codec = dai->component; + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + struct device *dev = codec->dev; + const unsigned int sample_rate = params_rate(params); + int sample_size, frame_size; + + /* Data sizes if not using TDM */ + sample_size = params_width(params); + + if (sample_size < 0) + return sample_size; + + frame_size = snd_soc_params_to_frame_size(params); + if (frame_size < 0) + return frame_size; + + if (cx2072x->mclk_rate == 0) { + dev_err(dev, "Master clock rate is not configued\n"); + return -EINVAL; + } + + if (cx2072x->bclk_ratio) + frame_size = cx2072x->bclk_ratio; + + switch (sample_rate) { + case 48000: + case 32000: + case 24000: + case 16000: + case 96000: + case 192000: + break; + + default: + dev_err(dev, "Unsupported sample rate %d\n", sample_rate); + return -EINVAL; + } + + dev_dbg(dev, "Sample size %d bits, frame = %d bits, rate = %d Hz\n", + sample_size, frame_size, sample_rate); + + cx2072x->frame_size = frame_size; + cx2072x->sample_size = sample_size; + cx2072x->sample_rate = sample_rate; + + if (dai->id == CX2072X_DAI_DSP) { + cx2072x->en_aec_ref = true; + dev_dbg(cx2072x->dev, "enables aec reference\n"); + regmap_write(cx2072x->regmap, + CX2072X_ADC1_CONNECTION_SELECT_CONTROL, 3); + } + + if (cx2072x->pll_changed) { + cx2072x_config_pll(cx2072x); + cx2072x->pll_changed = false; + } + + if (cx2072x->i2spcm_changed) { + cx2072x_config_i2spcm(cx2072x); + cx2072x->i2spcm_changed = false; + } + + return 0; +} + +static int cx2072x_set_dai_bclk_ratio(struct snd_soc_dai *dai, + unsigned int ratio) +{ + struct snd_soc_component *codec = dai->component; + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + + cx2072x->bclk_ratio = ratio; + return 0; +} + +static int cx2072x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_component *codec = dai->component; + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + + if (clk_set_rate(cx2072x->mclk, freq)) { + dev_err(codec->dev, "set clk rate failed\n"); + return -EINVAL; + } + + cx2072x->mclk_rate = freq; + return 0; +} + +static int cx2072x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *codec = dai->component; + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + struct device *dev = codec->dev; + + dev_dbg(dev, "set_dai_fmt- %08x\n", fmt); + /* set master/slave */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBS_CFS: + break; + + default: + dev_err(dev, "Unsupported DAI master mode\n"); + return -EINVAL; + } + + /* set format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + break; + + default: + dev_err(dev, "Unsupported DAI format\n"); + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + case SND_SOC_DAIFMT_IB_IF: + case SND_SOC_DAIFMT_IB_NF: + case SND_SOC_DAIFMT_NB_IF: + break; + + default: + dev_err(dev, "Unsupported DAI clock inversion\n"); + return -EINVAL; + } + + cx2072x->dai_fmt = fmt; + return 0; +} + +static const struct snd_kcontrol_new portaouten_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_PORTA_PIN_CTRL, 6, 1, 0); + +static const struct snd_kcontrol_new porteouten_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_PORTE_PIN_CTRL, 6, 1, 0); + +static const struct snd_kcontrol_new portgouten_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_PORTG_PIN_CTRL, 6, 1, 0); + +static const struct snd_kcontrol_new portmouten_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_PORTM_PIN_CTRL, 6, 1, 0); + +static const struct snd_kcontrol_new portbinen_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_PORTB_PIN_CTRL, 5, 1, 0); + +static const struct snd_kcontrol_new portcinen_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_PORTC_PIN_CTRL, 5, 1, 0); + +static const struct snd_kcontrol_new portdinen_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_PORTD_PIN_CTRL, 5, 1, 0); + +static const struct snd_kcontrol_new porteinen_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_PORTE_PIN_CTRL, 5, 1, 0); + +static const struct snd_kcontrol_new i2sadc1l_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2, 0, 1, 0); + +static const struct snd_kcontrol_new i2sadc1r_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2, 1, 1, 0); + +static const struct snd_kcontrol_new i2sadc2l_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2, 2, 1, 0); + +static const struct snd_kcontrol_new i2sadc2r_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2, 3, 1, 0); + +static const struct snd_kcontrol_new i2sdac1l_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3, 0, 1, 0); + +static const struct snd_kcontrol_new i2sdac1r_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3, 1, 1, 0); + +static const struct snd_kcontrol_new i2sdac2l_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3, 2, 1, 0); + +static const struct snd_kcontrol_new i2sdac2r_ctl = + SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3, 3, 1, 0); + +static const char * const dac_enum_text[] = { + "DAC1 Switch", "DAC2 Switch", +}; + +static const struct soc_enum porta_dac_enum = +SOC_ENUM_SINGLE(CX2072X_PORTA_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text); + +static const struct snd_kcontrol_new porta_mux = +SOC_DAPM_ENUM("PortA Mux", porta_dac_enum); + +static const struct soc_enum portg_dac_enum = +SOC_ENUM_SINGLE(CX2072X_PORTG_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text); + +static const struct snd_kcontrol_new portg_mux = +SOC_DAPM_ENUM("PortG Mux", portg_dac_enum); + +static const struct soc_enum porte_dac_enum = +SOC_ENUM_SINGLE(CX2072X_PORTE_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text); + +static const struct snd_kcontrol_new porte_mux = +SOC_DAPM_ENUM("PortE Mux", porte_dac_enum); + +static const struct soc_enum portm_dac_enum = +SOC_ENUM_SINGLE(CX2072X_PORTM_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text); + +static const struct snd_kcontrol_new portm_mux = +SOC_DAPM_ENUM("PortM Mux", portm_dac_enum); + +static const char * const adc1in_sel_text[] = { + "PortB Switch", "PortD Switch", "PortC Switch", "Widget15 Switch", + "PortE Switch", "PortF Switch", "PortH Switch" +}; + +static const struct soc_enum adc1in_sel_enum = +SOC_ENUM_SINGLE(CX2072X_ADC1_CONNECTION_SELECT_CONTROL, 0, 7, adc1in_sel_text); + +static const struct snd_kcontrol_new adc1_mux = +SOC_DAPM_ENUM("ADC1 Mux", adc1in_sel_enum); + +static const char * const adc2in_sel_text[] = { + "PortC Switch", "Widget15 Switch", "PortH Switch" +}; + +static const struct soc_enum adc2in_sel_enum = +SOC_ENUM_SINGLE(CX2072X_ADC2_CONNECTION_SELECT_CONTROL, 0, 3, adc2in_sel_text); + +static const struct snd_kcontrol_new adc2_mux = +SOC_DAPM_ENUM("ADC2 Mux", adc2in_sel_enum); + +static const struct snd_kcontrol_new wid15_mix[] = { + SOC_DAPM_SINGLE("DAC1L Switch", CX2072X_MIXER_GAIN_LEFT_0, 7, 1, 1), + SOC_DAPM_SINGLE("DAC1R Switch", CX2072X_MIXER_GAIN_RIGHT_0, 7, 1, 1), + SOC_DAPM_SINGLE("DAC2L Switch", CX2072X_MIXER_GAIN_LEFT_1, 7, 1, 1), + SOC_DAPM_SINGLE("DAC2R Switch", CX2072X_MIXER_GAIN_RIGHT_1, 7, 1, 1), +}; + +#define CX2072X_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, wmask, won_val, \ + woff_val, wevent, wflags) \ + {.id = snd_soc_dapm_supply, .name = wname, .kcontrol_news = NULL, \ + .num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \ + .on_val = won_val, .off_val = woff_val, \ + .subseq = wsubseq, .event = wevent, .event_flags = wflags} + +#define CX2072X_DAPM_SWITCH(wname, wreg, wshift, wmask, won_val, woff_val, \ + wevent, wflags) \ + {.id = snd_soc_dapm_switch, .name = wname, .kcontrol_news = NULL, \ + .num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \ + .on_val = won_val, .off_val = woff_val, \ + .event = wevent, .event_flags = wflags} + +#define CX2072X_DAPM_SWITCH(wname, wreg, wshift, wmask, won_val, woff_val, \ + wevent, wflags) \ + {.id = snd_soc_dapm_switch, .name = wname, .kcontrol_news = NULL, \ + .num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \ + .on_val = won_val, .off_val = woff_val, \ + .event = wevent, .event_flags = wflags} + +#define CX2072X_DAPM_REG_E(wid, wname, wreg, wshift, wmask, won_val, woff_val, \ + wevent, wflags) \ + {.id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \ + .reg = wreg, .shift = wshift, .mask = wmask, \ + .on_val = won_val, .off_val = woff_val, \ + .event = wevent, .event_flags = wflags} + +static const struct snd_soc_dapm_widget cx2072x_dapm_widgets[] = { + /*Playback*/ + SND_SOC_DAPM_AIF_IN("In AIF", "Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SWITCH("I2S DAC1L", SND_SOC_NOPM, 0, 0, &i2sdac1l_ctl), + SND_SOC_DAPM_SWITCH("I2S DAC1R", SND_SOC_NOPM, 0, 0, &i2sdac1r_ctl), + SND_SOC_DAPM_SWITCH("I2S DAC2L", SND_SOC_NOPM, 0, 0, &i2sdac2l_ctl), + SND_SOC_DAPM_SWITCH("I2S DAC2R", SND_SOC_NOPM, 0, 0, &i2sdac2r_ctl), + + SND_SOC_DAPM_REG(snd_soc_dapm_dac, "DAC1", CX2072X_DAC1_POWER_STATE, + 0, 0xfff, 0x00, 0x03), + + SND_SOC_DAPM_REG(snd_soc_dapm_dac, "DAC2", CX2072X_DAC2_POWER_STATE, + 0, 0xfff, 0x00, 0x03), + + SND_SOC_DAPM_MUX("PortA Mux", SND_SOC_NOPM, 0, 0, &porta_mux), + SND_SOC_DAPM_MUX("PortG Mux", SND_SOC_NOPM, 0, 0, &portg_mux), + SND_SOC_DAPM_MUX("PortE Mux", SND_SOC_NOPM, 0, 0, &porte_mux), + SND_SOC_DAPM_MUX("PortM Mux", SND_SOC_NOPM, 0, 0, &portm_mux), + + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortA Power", + CX2072X_PORTA_POWER_STATE, 0, 0xfff, 0x00, 0x03), + + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortM Power", + CX2072X_PORTM_POWER_STATE, 0, 0xfff, 0x00, 0x03), + + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortG Power", + CX2072X_PORTG_POWER_STATE, 0, 0xfff, 0x00, 0x03), + + CX2072X_DAPM_SUPPLY_S("AFG Power", 0, CX2072X_AFG_POWER_STATE, + 0, 0xfff, 0x00, 0x03, afg_power_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SWITCH("PortA Out En", SND_SOC_NOPM, 0, 0, + &portaouten_ctl), + SND_SOC_DAPM_SWITCH("PortE Out En", SND_SOC_NOPM, 0, 0, + &porteouten_ctl), + SND_SOC_DAPM_SWITCH("PortG Out En", SND_SOC_NOPM, 0, 0, + &portgouten_ctl), + SND_SOC_DAPM_SWITCH("PortM Out En", SND_SOC_NOPM, 0, 0, + &portmouten_ctl), + + SND_SOC_DAPM_OUTPUT("PORTA"), + SND_SOC_DAPM_OUTPUT("PORTG"), + SND_SOC_DAPM_OUTPUT("PORTE"), + SND_SOC_DAPM_OUTPUT("PORTM"), + SND_SOC_DAPM_OUTPUT("AEC REF"), + + /*Capture*/ + SND_SOC_DAPM_AIF_OUT("Out AIF", "Capture", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SWITCH("I2S ADC1L", SND_SOC_NOPM, 0, 0, &i2sadc1l_ctl), + SND_SOC_DAPM_SWITCH("I2S ADC1R", SND_SOC_NOPM, 0, 0, &i2sadc1r_ctl), + SND_SOC_DAPM_SWITCH("I2S ADC2L", SND_SOC_NOPM, 0, 0, &i2sadc2l_ctl), + SND_SOC_DAPM_SWITCH("I2S ADC2R", SND_SOC_NOPM, 0, 0, &i2sadc2r_ctl), + + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC1", CX2072X_ADC1_POWER_STATE, + 0, 0xff, 0x00, 0x03), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC2", CX2072X_ADC2_POWER_STATE, + 0, 0xff, 0x00, 0x03), + + SND_SOC_DAPM_MUX("ADC1 Mux", SND_SOC_NOPM, 0, 0, &adc1_mux), + SND_SOC_DAPM_MUX("ADC2 Mux", SND_SOC_NOPM, 0, 0, &adc2_mux), + + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortB Power", + CX2072X_PORTB_POWER_STATE, 0, 0xfff, 0x00, 0x03), + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortC Power", + CX2072X_PORTC_POWER_STATE, 0, 0xfff, 0x00, 0x03), + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortD Power", + CX2072X_PORTD_POWER_STATE, 0, 0xfff, 0x00, 0x03), + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortE Power", + CX2072X_PORTE_POWER_STATE, 0, 0xfff, 0x00, 0x03), + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Widget15 Power", + CX2072X_MIXER_POWER_STATE, 0, 0xfff, 0x00, 0x03), + + SND_SOC_DAPM_MIXER("Widget15 Mixer", SND_SOC_NOPM, 0, 0, + wid15_mix, ARRAY_SIZE(wid15_mix)), + SND_SOC_DAPM_SWITCH("PortB In En", SND_SOC_NOPM, 0, 0, &portbinen_ctl), + SND_SOC_DAPM_SWITCH("PortC In En", SND_SOC_NOPM, 0, 0, &portcinen_ctl), + SND_SOC_DAPM_SWITCH("PortD In En", SND_SOC_NOPM, 0, 0, &portdinen_ctl), + SND_SOC_DAPM_SWITCH("PortE In En", SND_SOC_NOPM, 0, 0, &porteinen_ctl), + + SND_SOC_DAPM_MICBIAS("Headset Bias", CX2072X_ANALOG_TEST11, 1, 0), + SND_SOC_DAPM_MICBIAS("PortB Mic Bias", CX2072X_PORTB_PIN_CTRL, 2, 0), + SND_SOC_DAPM_MICBIAS("PortD Mic Bias", CX2072X_PORTD_PIN_CTRL, 2, 0), + SND_SOC_DAPM_MICBIAS("PortE Mic Bias", CX2072X_PORTE_PIN_CTRL, 2, 0), + SND_SOC_DAPM_INPUT("PORTB"), + SND_SOC_DAPM_INPUT("PORTC"), + SND_SOC_DAPM_INPUT("PORTD"), + SND_SOC_DAPM_INPUT("PORTEIN"), + +}; + +static const struct snd_soc_dapm_route cx2072x_intercon[] = { + /* Playback */ + {"In AIF", NULL, "AFG Power"}, + {"I2S DAC1L", "Switch", "In AIF"}, + {"I2S DAC1R", "Switch", "In AIF"}, + {"I2S DAC2L", "Switch", "In AIF"}, + {"I2S DAC2R", "Switch", "In AIF"}, + {"DAC1", NULL, "I2S DAC1L"}, + {"DAC1", NULL, "I2S DAC1R"}, + {"DAC2", NULL, "I2S DAC2L"}, + {"DAC2", NULL, "I2S DAC2R"}, + {"PortA Mux", "DAC1 Switch", "DAC1"}, + {"PortA Mux", "DAC2 Switch", "DAC2"}, + {"PortG Mux", "DAC1 Switch", "DAC1"}, + {"PortG Mux", "DAC2 Switch", "DAC2"}, + {"PortE Mux", "DAC1 Switch", "DAC1"}, + {"PortE Mux", "DAC2 Switch", "DAC2"}, + {"PortM Mux", "DAC1 Switch", "DAC1"}, + {"PortM Mux", "DAC2 Switch", "DAC2"}, + {"Widget15 Mixer", "DAC1L Switch", "DAC1"}, + {"Widget15 Mixer", "DAC1R Switch", "DAC2"}, + {"Widget15 Mixer", "DAC2L Switch", "DAC1"}, + {"Widget15 Mixer", "DAC2R Switch", "DAC2"}, + {"Widget15 Mixer", NULL, "Widget15 Power"}, + {"PortA Out En", "Switch", "PortA Mux"}, + {"PortG Out En", "Switch", "PortG Mux"}, + {"PortE Out En", "Switch", "PortE Mux"}, + {"PortM Out En", "Switch", "PortM Mux"}, + {"PortA Mux", NULL, "PortA Power"}, + {"PortG Mux", NULL, "PortG Power"}, + {"PortE Mux", NULL, "PortE Power"}, + {"PortM Mux", NULL, "PortM Power"}, + {"PortA Out En", NULL, "PortA Power"}, + {"PortG Out En", NULL, "PortG Power"}, + {"PortE Out En", NULL, "PortE Power"}, + {"PortM Out En", NULL, "PortM Power"}, + {"PORTA", NULL, "PortA Out En"}, + {"PORTG", NULL, "PortG Out En"}, + {"PORTE", NULL, "PortE Out En"}, + {"PORTM", NULL, "PortM Out En"}, + + /* Capture */ + {"PORTD", NULL, "Headset Bias"}, + {"PortB In En", "Switch", "PORTB"}, + {"PortC In En", "Switch", "PORTC"}, + {"PortD In En", "Switch", "PORTD"}, + {"PortE In En", "Switch", "PORTEIN"}, + {"ADC1 Mux", "PortB Switch", "PortB In En"}, + {"ADC1 Mux", "PortC Switch", "PortC In En"}, + {"ADC1 Mux", "PortD Switch", "PortD In En"}, + {"ADC1 Mux", "PortE Switch", "PortE In En"}, + {"ADC1 Mux", "Widget15 Switch", "Widget15 Mixer"}, + {"ADC2 Mux", "PortC Switch", "PortC In En"}, + {"ADC2 Mux", "Widget15 Switch", "Widget15 Mixer"}, + {"ADC1", NULL, "ADC1 Mux"}, + {"ADC2", NULL, "ADC2 Mux"}, + {"I2S ADC1L", "Switch", "ADC1"}, + {"I2S ADC1R", "Switch", "ADC1"}, + {"I2S ADC2L", "Switch", "ADC2"}, + {"I2S ADC2R", "Switch", "ADC2"}, + {"Out AIF", NULL, "I2S ADC1L"}, + {"Out AIF", NULL, "I2S ADC1R"}, + {"Out AIF", NULL, "I2S ADC2L"}, + {"Out AIF", NULL, "I2S ADC2R"}, + {"Out AIF", NULL, "AFG Power"}, + {"AEC REF", NULL, "Out AIF"}, + {"PortB In En", NULL, "PortB Power"}, + {"PortC In En", NULL, "PortC Power"}, + {"PortD In En", NULL, "PortD Power"}, + {"PortE In En", NULL, "PortE Power"}, +}; + +static int cx2072x_set_bias_level(struct snd_soc_component *codec, + enum snd_soc_bias_level level) +{ + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + const enum snd_soc_bias_level old_level = + snd_soc_component_get_bias_level(codec); + + if (level == SND_SOC_BIAS_STANDBY && old_level == SND_SOC_BIAS_OFF) + regmap_write(cx2072x->regmap, CX2072X_AFG_POWER_STATE, 0); + else if (level == SND_SOC_BIAS_OFF && old_level != SND_SOC_BIAS_OFF) + regmap_write(cx2072x->regmap, CX2072X_AFG_POWER_STATE, 3); + + return 0; +} + +/* + * FIXME: the whole jack detection code below is pretty platform-specific; + * it has lots of implicit assumptions about the pins, etc. + * However, since we have no other code and reference, take this hard-coded + * setup for now. Once when we have different platform implementations, + * this needs to be rewritten in a more generic form, or moving into the + * platform data. + */ +static void cx2072x_enable_jack_detect(struct snd_soc_component *codec) +{ + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec); + + /* No-sticky input type */ + regmap_write(cx2072x->regmap, CX2072X_GPIO_STICKY_MASK, 0x1f); + + /* Use GPOI0 as interrupt pin */ + regmap_write(cx2072x->regmap, CX2072X_UM_INTERRUPT_CRTL_E, 0x12 << 24); + + /* Enables unsolitited message on PortA */ + regmap_write(cx2072x->regmap, CX2072X_PORTA_UNSOLICITED_RESPONSE, 0x80); + + /* support both nokia and apple headset set. Monitor time = 275 ms */ + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST15, 0x73); + + /* Disable TIP detection */ + regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST12, 0x300); + + /* Switch MusicD3Live pin to GPIO */ + regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST1, 0); + + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PORTD"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "Headset Bias"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PortD Mic Bias"); + + snd_soc_dapm_mutex_unlock(dapm); +} + +static void cx2072x_disable_jack_detect(struct snd_soc_component *codec) +{ + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + + regmap_write(cx2072x->regmap, CX2072X_UM_INTERRUPT_CRTL_E, 0); + regmap_write(cx2072x->regmap, CX2072X_PORTA_UNSOLICITED_RESPONSE, 0); +} + +static int cx2072x_jack_status_check(void *data) +{ + struct snd_soc_component *codec = data; + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + unsigned int jack; + unsigned int type = 0; + int state = 0; + + mutex_lock(&cx2072x->lock); + + regmap_read(cx2072x->regmap, CX2072X_PORTA_PIN_SENSE, &jack); + jack = jack >> 24; + regmap_read(cx2072x->regmap, CX2072X_DIGITAL_TEST11, &type); + + if (jack == 0x80) { + type = type >> 8; + + if (type & 0x8) { + /* Apple headset */ + state |= SND_JACK_HEADSET; + if (type & 0x2) + state |= SND_JACK_BTN_0; + } else if (type & 0x4) { + /* Nokia headset */ + state |= SND_JACK_HEADPHONE; + } else { + /* Headphone */ + state |= SND_JACK_HEADPHONE; + } + } + + /* clear interrupt */ + regmap_write(cx2072x->regmap, CX2072X_UM_INTERRUPT_CRTL_E, 0x12 << 24); + + mutex_unlock(&cx2072x->lock); + + dev_dbg(codec->dev, "CX2072X_HSDETECT type=0x%X,Jack state = %x\n", + type, state); + return state; +} + +static const struct snd_soc_jack_gpio cx2072x_jack_gpio = { + .name = "headset", + .report = SND_JACK_HEADSET | SND_JACK_BTN_0, + .debounce_time = 150, + .wake = true, + .jack_status_check = cx2072x_jack_status_check, +}; + +static int cx2072x_set_jack(struct snd_soc_component *codec, + struct snd_soc_jack *jack, void *data) +{ + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + int err; + + if (!jack) { + cx2072x_disable_jack_detect(codec); + return 0; + } + + if (!cx2072x->jack_gpio.gpiod_dev) { + cx2072x->jack_gpio = cx2072x_jack_gpio; + cx2072x->jack_gpio.gpiod_dev = codec->dev; + cx2072x->jack_gpio.data = codec; + err = snd_soc_jack_add_gpios(jack, 1, &cx2072x->jack_gpio); + if (err) { + cx2072x->jack_gpio.gpiod_dev = NULL; + return err; + } + } + + cx2072x_enable_jack_detect(codec); + return 0; +} + +static int cx2072x_probe(struct snd_soc_component *codec) +{ + struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(codec); + + cx2072x->codec = codec; + + /* + * FIXME: below is, again, a very platform-specific init sequence, + * but we keep the code here just for simplicity. It seems that all + * existing hardware implementations require this, so there is no very + * much reason to move this out of the codec driver to the platform + * data. + * But of course it's no "right" thing; if you are a good boy, don't + * read and follow the code like this! + */ + pm_runtime_get_sync(codec->dev); + regmap_write(cx2072x->regmap, CX2072X_AFG_POWER_STATE, 0); + + regmap_multi_reg_write(cx2072x->regmap, cx2072x_reg_init, + ARRAY_SIZE(cx2072x_reg_init)); + + /* configre PortC as input device */ + regmap_update_bits(cx2072x->regmap, CX2072X_PORTC_PIN_CTRL, + 0x20, 0x20); + + regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST2, + 0x84, 0xff); + + regmap_write(cx2072x->regmap, CX2072X_AFG_POWER_STATE, 3); + pm_runtime_put(codec->dev); + + return 0; +} + +static const struct snd_soc_component_driver soc_codec_driver_cx2072x = { + .probe = cx2072x_probe, + .set_bias_level = cx2072x_set_bias_level, + .set_jack = cx2072x_set_jack, + .controls = cx2072x_snd_controls, + .num_controls = ARRAY_SIZE(cx2072x_snd_controls), + .dapm_widgets = cx2072x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cx2072x_dapm_widgets), + .dapm_routes = cx2072x_intercon, + .num_dapm_routes = ARRAY_SIZE(cx2072x_intercon), +}; + +/* + * DAI ops + */ +static struct snd_soc_dai_ops cx2072x_dai_ops = { + .set_sysclk = cx2072x_set_dai_sysclk, + .set_fmt = cx2072x_set_dai_fmt, + .hw_params = cx2072x_hw_params, + .set_bclk_ratio = cx2072x_set_dai_bclk_ratio, +}; + +static int cx2072x_dsp_dai_probe(struct snd_soc_dai *dai) +{ + struct cx2072x_priv *cx2072x = + snd_soc_component_get_drvdata(dai->component); + + cx2072x->en_aec_ref = true; + return 0; +} + +#define CX2072X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) + +static struct snd_soc_dai_driver soc_codec_cx2072x_dai[] = { + { /* playback and capture */ + .name = "cx2072x-hifi", + .id = CX2072X_DAI_HIFI, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = CX2072X_RATES_DSP, + .formats = CX2072X_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = CX2072X_RATES_DSP, + .formats = CX2072X_FORMATS, + }, + .ops = &cx2072x_dai_ops, + .symmetric_rates = 1, + }, + { /* plabayck only, return echo reference to Conexant DSP chip */ + .name = "cx2072x-dsp", + .id = CX2072X_DAI_DSP, + .probe = cx2072x_dsp_dai_probe, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = CX2072X_RATES_DSP, + .formats = CX2072X_FORMATS, + }, + .ops = &cx2072x_dai_ops, + }, + { /* plabayck only, return echo reference through I2S TX */ + .name = "cx2072x-aec", + .id = 3, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = CX2072X_RATES_DSP, + .formats = CX2072X_FORMATS, + }, + }, +}; + +static const struct regmap_config cx2072x_regmap = { + .reg_bits = 16, + .val_bits = 32, + .max_register = CX2072X_REG_MAX, + .reg_defaults = cx2072x_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cx2072x_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .readable_reg = cx2072x_readable_register, + .volatile_reg = cx2072x_volatile_register, + /* Needs custom read/write functions for various register lengths */ + .reg_read = cx2072x_reg_read, + .reg_write = cx2072x_reg_write, +}; + +static int __maybe_unused cx2072x_runtime_suspend(struct device *dev) +{ + struct cx2072x_priv *cx2072x = dev_get_drvdata(dev); + + clk_disable_unprepare(cx2072x->mclk); + return 0; +} + +static int cx2072x_runtime_resume(struct device *dev) +{ + struct cx2072x_priv *cx2072x = dev_get_drvdata(dev); + + return clk_prepare_enable(cx2072x->mclk); +} + +static int cx2072x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct cx2072x_priv *cx2072x; + unsigned int ven_id, rev_id; + int ret; + + cx2072x = devm_kzalloc(&i2c->dev, sizeof(struct cx2072x_priv), + GFP_KERNEL); + if (!cx2072x) + return -ENOMEM; + + cx2072x->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, + &cx2072x_regmap); + if (IS_ERR(cx2072x->regmap)) + return PTR_ERR(cx2072x->regmap); + + mutex_init(&cx2072x->lock); + + i2c_set_clientdata(i2c, cx2072x); + + cx2072x->dev = &i2c->dev; + cx2072x->pll_changed = true; + cx2072x->i2spcm_changed = true; + cx2072x->bclk_ratio = 0; + + cx2072x->mclk = devm_clk_get(cx2072x->dev, "mclk"); + if (IS_ERR(cx2072x->mclk)) { + dev_err(cx2072x->dev, "Failed to get MCLK\n"); + return PTR_ERR(cx2072x->mclk); + } + + regmap_read(cx2072x->regmap, CX2072X_VENDOR_ID, &ven_id); + regmap_read(cx2072x->regmap, CX2072X_REVISION_ID, &rev_id); + + dev_info(cx2072x->dev, "codec version: %08x,%08x\n", ven_id, rev_id); + + ret = devm_snd_soc_register_component(cx2072x->dev, + &soc_codec_driver_cx2072x, + soc_codec_cx2072x_dai, + ARRAY_SIZE(soc_codec_cx2072x_dai)); + if (ret < 0) + return ret; + + pm_runtime_use_autosuspend(cx2072x->dev); + pm_runtime_enable(cx2072x->dev); + + return 0; +} + +static int cx2072x_i2c_remove(struct i2c_client *i2c) +{ + pm_runtime_disable(&i2c->dev); + return 0; +} + +static const struct i2c_device_id cx2072x_i2c_id[] = { + { "cx20721", 0 }, + { "cx20723", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cx2072x_i2c_id); + +#ifdef CONFIG_ACPI +static struct acpi_device_id cx2072x_acpi_match[] = { + { "14F10720", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, cx2072x_acpi_match); +#endif + +static const struct dev_pm_ops cx2072x_runtime_pm = { + SET_RUNTIME_PM_OPS(cx2072x_runtime_suspend, cx2072x_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct i2c_driver cx2072x_i2c_driver = { + .driver = { + .name = "cx2072x", + .acpi_match_table = ACPI_PTR(cx2072x_acpi_match), + .pm = &cx2072x_runtime_pm, + }, + .probe = cx2072x_i2c_probe, + .remove = cx2072x_i2c_remove, + .id_table = cx2072x_i2c_id, +}; + +module_i2c_driver(cx2072x_i2c_driver); + +MODULE_DESCRIPTION("ASoC cx2072x Codec Driver"); +MODULE_AUTHOR("Simon Ho "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cx2072x.h b/sound/soc/codecs/cx2072x.h new file mode 100644 index 000000000000..ebdd567fa225 --- /dev/null +++ b/sound/soc/codecs/cx2072x.h @@ -0,0 +1,314 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ALSA SoC CX20721/CX20723 codec driver + * + * Copyright: (C) 2017 Conexant Systems, Inc. + * Author: Simon Ho, + */ + +#ifndef __CX2072X_H__ +#define __CX2072X_H__ + +#define CX2072X_MCLK_PLL 1 +#define CX2072X_MCLK_EXTERNAL_PLL 1 +#define CX2072X_MCLK_INTERNAL_OSC 2 + +/*#define CX2072X_RATES SNDRV_PCM_RATE_8000_192000*/ +#define CX2072X_RATES_DSP SNDRV_PCM_RATE_48000 + +#define CX2072X_REG_MAX 0x8a3c + +#define CX2072X_VENDOR_ID 0x0200 +#define CX2072X_REVISION_ID 0x0208 +#define CX2072X_CURRENT_BCLK_FREQUENCY 0x00dc +#define CX2072X_AFG_POWER_STATE 0x0414 +#define CX2072X_UM_RESPONSE 0x0420 +#define CX2072X_GPIO_DATA 0x0454 +#define CX2072X_GPIO_ENABLE 0x0458 +#define CX2072X_GPIO_DIRECTION 0x045c +#define CX2072X_GPIO_WAKE 0x0460 +#define CX2072X_GPIO_UM_ENABLE 0x0464 +#define CX2072X_GPIO_STICKY_MASK 0x0468 +#define CX2072X_AFG_FUNCTION_RESET 0x07fc +#define CX2072X_DAC1_CONVERTER_FORMAT 0x43c8 +#define CX2072X_DAC1_AMP_GAIN_RIGHT 0x41c0 +#define CX2072X_DAC1_AMP_GAIN_LEFT 0x41e0 +#define CX2072X_DAC1_POWER_STATE 0x4014 +#define CX2072X_DAC1_CONVERTER_STREAM_CHANNEL 0x4018 +#define CX2072X_DAC1_EAPD_ENABLE 0x4030 +#define CX2072X_DAC2_CONVERTER_FORMAT 0x47c8 +#define CX2072X_DAC2_AMP_GAIN_RIGHT 0x45c0 +#define CX2072X_DAC2_AMP_GAIN_LEFT 0x45e0 +#define CX2072X_DAC2_POWER_STATE 0x4414 +#define CX2072X_DAC2_CONVERTER_STREAM_CHANNEL 0x4418 +#define CX2072X_ADC1_CONVERTER_FORMAT 0x4fc8 +#define CX2072X_ADC1_AMP_GAIN_RIGHT_0 0x4d80 +#define CX2072X_ADC1_AMP_GAIN_LEFT_0 0x4da0 +#define CX2072X_ADC1_AMP_GAIN_RIGHT_1 0x4d84 +#define CX2072X_ADC1_AMP_GAIN_LEFT_1 0x4da4 +#define CX2072X_ADC1_AMP_GAIN_RIGHT_2 0x4d88 +#define CX2072X_ADC1_AMP_GAIN_LEFT_2 0x4da8 +#define CX2072X_ADC1_AMP_GAIN_RIGHT_3 0x4d8c +#define CX2072X_ADC1_AMP_GAIN_LEFT_3 0x4dac +#define CX2072X_ADC1_AMP_GAIN_RIGHT_4 0x4d90 +#define CX2072X_ADC1_AMP_GAIN_LEFT_4 0x4db0 +#define CX2072X_ADC1_AMP_GAIN_RIGHT_5 0x4d94 +#define CX2072X_ADC1_AMP_GAIN_LEFT_5 0x4db4 +#define CX2072X_ADC1_AMP_GAIN_RIGHT_6 0x4d98 +#define CX2072X_ADC1_AMP_GAIN_LEFT_6 0x4db8 +#define CX2072X_ADC1_CONNECTION_SELECT_CONTROL 0x4c04 +#define CX2072X_ADC1_POWER_STATE 0x4c14 +#define CX2072X_ADC1_CONVERTER_STREAM_CHANNEL 0x4c18 +#define CX2072X_ADC2_CONVERTER_FORMAT 0x53c8 +#define CX2072X_ADC2_AMP_GAIN_RIGHT_0 0x5180 +#define CX2072X_ADC2_AMP_GAIN_LEFT_0 0x51a0 +#define CX2072X_ADC2_AMP_GAIN_RIGHT_1 0x5184 +#define CX2072X_ADC2_AMP_GAIN_LEFT_1 0x51a4 +#define CX2072X_ADC2_AMP_GAIN_RIGHT_2 0x5188 +#define CX2072X_ADC2_AMP_GAIN_LEFT_2 0x51a8 +#define CX2072X_ADC2_CONNECTION_SELECT_CONTROL 0x5004 +#define CX2072X_ADC2_POWER_STATE 0x5014 +#define CX2072X_ADC2_CONVERTER_STREAM_CHANNEL 0x5018 +#define CX2072X_PORTA_CONNECTION_SELECT_CTRL 0x5804 +#define CX2072X_PORTA_POWER_STATE 0x5814 +#define CX2072X_PORTA_PIN_CTRL 0x581c +#define CX2072X_PORTA_UNSOLICITED_RESPONSE 0x5820 +#define CX2072X_PORTA_PIN_SENSE 0x5824 +#define CX2072X_PORTA_EAPD_BTL 0x5830 +#define CX2072X_PORTB_POWER_STATE 0x6014 +#define CX2072X_PORTB_PIN_CTRL 0x601c +#define CX2072X_PORTB_UNSOLICITED_RESPONSE 0x6020 +#define CX2072X_PORTB_PIN_SENSE 0x6024 +#define CX2072X_PORTB_EAPD_BTL 0x6030 +#define CX2072X_PORTB_GAIN_RIGHT 0x6180 +#define CX2072X_PORTB_GAIN_LEFT 0x61a0 +#define CX2072X_PORTC_POWER_STATE 0x6814 +#define CX2072X_PORTC_PIN_CTRL 0x681c +#define CX2072X_PORTC_GAIN_RIGHT 0x6980 +#define CX2072X_PORTC_GAIN_LEFT 0x69a0 +#define CX2072X_PORTD_POWER_STATE 0x6414 +#define CX2072X_PORTD_PIN_CTRL 0x641c +#define CX2072X_PORTD_UNSOLICITED_RESPONSE 0x6420 +#define CX2072X_PORTD_PIN_SENSE 0x6424 +#define CX2072X_PORTD_GAIN_RIGHT 0x6580 +#define CX2072X_PORTD_GAIN_LEFT 0x65a0 +#define CX2072X_PORTE_CONNECTION_SELECT_CTRL 0x7404 +#define CX2072X_PORTE_POWER_STATE 0x7414 +#define CX2072X_PORTE_PIN_CTRL 0x741c +#define CX2072X_PORTE_UNSOLICITED_RESPONSE 0x7420 +#define CX2072X_PORTE_PIN_SENSE 0x7424 +#define CX2072X_PORTE_EAPD_BTL 0x7430 +#define CX2072X_PORTE_GAIN_RIGHT 0x7580 +#define CX2072X_PORTE_GAIN_LEFT 0x75a0 +#define CX2072X_PORTF_POWER_STATE 0x7814 +#define CX2072X_PORTF_PIN_CTRL 0x781c +#define CX2072X_PORTF_UNSOLICITED_RESPONSE 0x7820 +#define CX2072X_PORTF_PIN_SENSE 0x7824 +#define CX2072X_PORTF_GAIN_RIGHT 0x7980 +#define CX2072X_PORTF_GAIN_LEFT 0x79a0 +#define CX2072X_PORTG_POWER_STATE 0x5c14 +#define CX2072X_PORTG_PIN_CTRL 0x5c1c +#define CX2072X_PORTG_CONNECTION_SELECT_CTRL 0x5c04 +#define CX2072X_PORTG_EAPD_BTL 0x5c30 +#define CX2072X_PORTM_POWER_STATE 0x8814 +#define CX2072X_PORTM_PIN_CTRL 0x881c +#define CX2072X_PORTM_CONNECTION_SELECT_CTRL 0x8804 +#define CX2072X_PORTM_EAPD_BTL 0x8830 +#define CX2072X_MIXER_POWER_STATE 0x5414 +#define CX2072X_MIXER_GAIN_RIGHT_0 0x5580 +#define CX2072X_MIXER_GAIN_LEFT_0 0x55a0 +#define CX2072X_MIXER_GAIN_RIGHT_1 0x5584 +#define CX2072X_MIXER_GAIN_LEFT_1 0x55a4 +#define CX2072X_EQ_ENABLE_BYPASS 0x6d00 +#define CX2072X_EQ_B0_COEFF 0x6d02 +#define CX2072X_EQ_B1_COEFF 0x6d04 +#define CX2072X_EQ_B2_COEFF 0x6d06 +#define CX2072X_EQ_A1_COEFF 0x6d08 +#define CX2072X_EQ_A2_COEFF 0x6d0a +#define CX2072X_EQ_G_COEFF 0x6d0c +#define CX2072X_EQ_BAND 0x6d0d +#define CX2072X_SPKR_DRC_ENABLE_STEP 0x6d10 +#define CX2072X_SPKR_DRC_CONTROL 0x6d14 +#define CX2072X_SPKR_DRC_TEST 0x6d18 +#define CX2072X_DIGITAL_BIOS_TEST0 0x6d80 +#define CX2072X_DIGITAL_BIOS_TEST2 0x6d84 +#define CX2072X_I2SPCM_CONTROL1 0x6e00 +#define CX2072X_I2SPCM_CONTROL2 0x6e04 +#define CX2072X_I2SPCM_CONTROL3 0x6e08 +#define CX2072X_I2SPCM_CONTROL4 0x6e0c +#define CX2072X_I2SPCM_CONTROL5 0x6e10 +#define CX2072X_I2SPCM_CONTROL6 0x6e18 +#define CX2072X_UM_INTERRUPT_CRTL_E 0x6e14 +#define CX2072X_CODEC_TEST2 0x7108 +#define CX2072X_CODEC_TEST9 0x7124 +#define CX2072X_CODEC_TESTXX 0x7290 +#define CX2072X_CODEC_TEST20 0x7310 +#define CX2072X_CODEC_TEST24 0x731c +#define CX2072X_CODEC_TEST26 0x7328 +#define CX2072X_ANALOG_TEST3 0x718c +#define CX2072X_ANALOG_TEST4 0x7190 +#define CX2072X_ANALOG_TEST5 0x7194 +#define CX2072X_ANALOG_TEST6 0x7198 +#define CX2072X_ANALOG_TEST7 0x719c +#define CX2072X_ANALOG_TEST8 0x71a0 +#define CX2072X_ANALOG_TEST9 0x71a4 +#define CX2072X_ANALOG_TEST10 0x71a8 +#define CX2072X_ANALOG_TEST11 0x71ac +#define CX2072X_ANALOG_TEST12 0x71b0 +#define CX2072X_ANALOG_TEST13 0x71b4 +#define CX2072X_DIGITAL_TEST0 0x7200 +#define CX2072X_DIGITAL_TEST1 0x7204 +#define CX2072X_DIGITAL_TEST11 0x722c +#define CX2072X_DIGITAL_TEST12 0x7230 +#define CX2072X_DIGITAL_TEST15 0x723c +#define CX2072X_DIGITAL_TEST16 0x7080 +#define CX2072X_DIGITAL_TEST17 0x7084 +#define CX2072X_DIGITAL_TEST18 0x7088 +#define CX2072X_DIGITAL_TEST19 0x708c +#define CX2072X_DIGITAL_TEST20 0x7090 + +/* not used in the current code, for future extensions (if any) */ +#define CX2072X_MAX_EQ_BAND 7 +#define CX2072X_MAX_EQ_COEFF 11 +#define CX2072X_MAX_DRC_REGS 9 +#define CX2072X_MIC_EQ_COEFF 10 +#define CX2072X_PLBK_EQ_BAND_NUM 7 +#define CX2072X_PLBK_EQ_COEF_LEN 11 +#define CX2072X_PLBK_DRC_PARM_LEN 9 +#define CX2072X_CLASSD_AMP_LEN 6 + +/* DAI interfae type */ +#define CX2072X_DAI_HIFI 1 +#define CX2072X_DAI_DSP 2 +#define CX2072X_DAI_DSP_PWM 3 /* 4 ch, including mic and AEC */ + +enum cx2072x_reg_sample_size { + CX2072X_SAMPLE_SIZE_8_BITS = 0, + CX2072X_SAMPLE_SIZE_16_BITS = 1, + CX2072X_SAMPLE_SIZE_24_BITS = 2, + CX2072X_SAMPLE_SIZE_RESERVED = 3, +}; + +union cx2072x_reg_i2spcm_ctrl_reg1 { + struct { + u32 rx_data_one_line:1; + u32 rx_ws_pol:1; + u32 rx_ws_wid:7; + u32 rx_frm_len:5; + u32 rx_sa_size:2; + u32 tx_data_one_line:1; + u32 tx_ws_pol:1; + u32 tx_ws_wid:7; + u32 tx_frm_len:5; + u32 tx_sa_size:2; + } r; + u32 ulval; +}; + +union cx2072x_reg_i2spcm_ctrl_reg2 { + struct { + u32 tx_en_ch1:1; + u32 tx_en_ch2:1; + u32 tx_en_ch3:1; + u32 tx_en_ch4:1; + u32 tx_en_ch5:1; + u32 tx_en_ch6:1; + u32 tx_slot_1:5; + u32 tx_slot_2:5; + u32 tx_slot_3:5; + u32 tx_slot_4:5; + u32 res:1; + u32 tx_data_neg_bclk:1; + u32 tx_master:1; + u32 tx_tri_n:1; + u32 tx_endian_sel:1; + u32 tx_dstart_dly:1; + } r; + u32 ulval; +}; + +union cx2072x_reg_i2spcm_ctrl_reg3 { + struct { + u32 rx_en_ch1:1; + u32 rx_en_ch2:1; + u32 rx_en_ch3:1; + u32 rx_en_ch4:1; + u32 rx_en_ch5:1; + u32 rx_en_ch6:1; + u32 rx_slot_1:5; + u32 rx_slot_2:5; + u32 rx_slot_3:5; + u32 rx_slot_4:5; + u32 res:1; + u32 rx_data_neg_bclk:1; + u32 rx_master:1; + u32 rx_tri_n:1; + u32 rx_endian_sel:1; + u32 rx_dstart_dly:1; + } r; + u32 ulval; +}; + +union cx2072x_reg_i2spcm_ctrl_reg4 { + struct { + u32 rx_mute:1; + u32 tx_mute:1; + u32 reserved:1; + u32 dac_34_independent:1; + u32 dac_bclk_lrck_share:1; + u32 bclk_lrck_share_en:1; + u32 reserved2:2; + u32 rx_last_dac_ch_en:1; + u32 rx_last_dac_ch:3; + u32 tx_last_adc_ch_en:1; + u32 tx_last_adc_ch:3; + u32 rx_slot_5:5; + u32 rx_slot_6:5; + u32 reserved3:6; + } r; + u32 ulval; +}; + +union cx2072x_reg_i2spcm_ctrl_reg5 { + struct { + u32 tx_slot_5:5; + u32 reserved:3; + u32 tx_slot_6:5; + u32 reserved2:3; + u32 reserved3:8; + u32 i2s_pcm_clk_div:7; + u32 i2s_pcm_clk_div_chan_en:1; + } r; + u32 ulval; +}; + +union cx2072x_reg_i2spcm_ctrl_reg6 { + struct { + u32 reserved:5; + u32 rx_pause_cycles:3; + u32 rx_pause_start_pos:8; + u32 reserved2:5; + u32 tx_pause_cycles:3; + u32 tx_pause_start_pos:8; + } r; + u32 ulval; +}; + +union cx2072x_reg_digital_bios_test2 { + struct { + u32 pull_down_eapd:2; + u32 input_en_eapd_pad:1; + u32 push_pull_mode:1; + u32 eapd_pad_output_driver:2; + u32 pll_source:1; + u32 i2s_bclk_en:1; + u32 i2s_bclk_invert:1; + u32 pll_ref_clock:1; + u32 class_d_shield_clk:1; + u32 audio_pll_bypass_mode:1; + u32 reserved:4; + } r; + u32 ulval; +}; + +#endif /* __CX2072X_H__ */ From 3917da94f787e6c907e440653ead0c666a71379e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 May 2019 08:26:53 +0200 Subject: [PATCH 066/626] ASoC: Intel: Add machine driver for CX2072X on BYT/CHT platforms This is an implementation of a machine driver needed for Conexant CX2072X codec on Intel Baytrail and Cherrytrail platforms. The current patch is based on the initial work by Pierre-Louis Bossart and the other Intel machine drivers. The jack detection support (driven via the standard GPIO) was added on top of the original work. Tested with ASUS E200HA laptop. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=115531 Acked-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 11 + sound/soc/intel/boards/Makefile | 2 + sound/soc/intel/boards/bytcht_cx2072x.c | 262 ++++++++++++++++++ .../intel/common/soc-acpi-intel-byt-match.c | 8 + .../intel/common/soc-acpi-intel-cht-match.c | 8 + 5 files changed, 291 insertions(+) create mode 100644 sound/soc/intel/boards/bytcht_cx2072x.c diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index e39473a6a5d9..59e366edc16b 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -155,6 +155,17 @@ config SND_SOC_INTEL_CHT_BSW_NAU8824_MACH Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_BYT_CHT_CX2072X_MACH + tristate "Baytrail & Cherrytrail with CX2072X codec" + depends on X86_INTEL_LPSS && I2C && ACPI + select SND_SOC_ACPI + select SND_SOC_CX2072X + help + This adds support for ASoC machine driver for Intel(R) Baytrail & + Cherrytrail platforms with Conexant CX2072X audio codec. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_BYT_CHT_DA7213_MACH tristate "Baytrail & Cherrytrail with DA7212/7213 codec" depends on I2C && ACPI diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 451b3bd7d9c5..6445f90ea542 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -13,6 +13,7 @@ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o snd-soc-sst-cht-bsw-nau8824-objs := cht_bsw_nau8824.o +snd-soc-sst-byt-cht-cx2072x-objs := bytcht_cx2072x.o snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o @@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH) += snd-soc-sst-cht-bsw-nau8824.o +obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH) += snd-soc-sst-byt-cht-cx2072x.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c new file mode 100644 index 000000000000..b21b0e7f981a --- /dev/null +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// ASoC DPCM Machine driver for Baytrail / Cherrytrail platforms with +// CX2072X codec +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../codecs/cx2072x.h" +#include "../atom/sst-atom-controls.h" + +static const struct snd_soc_dapm_widget byt_cht_cx2072x_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), +}; + +static const struct snd_soc_dapm_route byt_cht_cx2072x_audio_map[] = { + /* External Speakers: HFL, HFR */ + {"Headphone", NULL, "PORTA"}, + {"Ext Spk", NULL, "PORTG"}, + {"PORTC", NULL, "Int Mic"}, + {"PORTD", NULL, "Headset Mic"}, + + {"Playback", NULL, "ssp2 Tx"}, + {"ssp2 Tx", NULL, "codec_out0"}, + {"ssp2 Tx", NULL, "codec_out1"}, + {"codec_in0", NULL, "ssp2 Rx"}, + {"codec_in1", NULL, "ssp2 Rx"}, + {"ssp2 Rx", NULL, "Capture"}, +}; + +static const struct snd_kcontrol_new byt_cht_cx2072x_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), + SOC_DAPM_PIN_SWITCH("Ext Spk"), +}; + +static struct snd_soc_jack byt_cht_cx2072x_headset; + +/* Headset jack detection DAPM pins */ +static struct snd_soc_jack_pin byt_cht_cx2072x_headset_pins[] = { + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, +}; + +static const struct acpi_gpio_params byt_cht_cx2072x_headset_gpios; +static const struct acpi_gpio_mapping byt_cht_cx2072x_acpi_gpios[] = { + { "headset-gpios", &byt_cht_cx2072x_headset_gpios, 1 }, + {}, +}; + +static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_component *codec = rtd->codec_dai->component; + int ret; + + if (devm_acpi_dev_add_driver_gpios(codec->dev, + byt_cht_cx2072x_acpi_gpios)) + dev_warn(rtd->dev, "Unable to add GPIO mapping table\n"); + + card->dapm.idle_bias_off = true; + + /* set the default PLL rate, the clock is handled by the codec driver */ + ret = snd_soc_dai_set_sysclk(rtd->codec_dai, CX2072X_MCLK_EXTERNAL_PLL, + 19200000, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(rtd->dev, "Could not set sysclk\n"); + return ret; + } + + ret = snd_soc_card_jack_new(card, "Headset", + SND_JACK_HEADSET | SND_JACK_BTN_0, + &byt_cht_cx2072x_headset, + byt_cht_cx2072x_headset_pins, + ARRAY_SIZE(byt_cht_cx2072x_headset_pins)); + if (ret) + return ret; + + snd_soc_component_set_jack(codec, &byt_cht_cx2072x_headset, NULL); + + snd_soc_dai_set_bclk_ratio(rtd->codec_dai, 50); + + return ret; +} + +static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate = + hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = + hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + int ret; + + /* The DSP will covert the FE rate to 48k, stereo, 24bits */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP2 to 24-bit */ + params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + + /* + * Default mode for SSP configuration is TDM 4 slot, override config + * with explicit setting to I2S 2ch 24-bit. The word length is set with + * dai_set_tdm_slot() since there is no other API exposed + */ + ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) { + dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); + if (ret < 0) { + dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); + return ret; + } + + return 0; +} + +static int byt_cht_cx2072x_aif1_startup(struct snd_pcm_substream *substream) +{ + return snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, 48000); +} + +static struct snd_soc_ops byt_cht_cx2072x_aif1_ops = { + .startup = byt_cht_cx2072x_aif1_startup, +}; + +static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = { + [MERR_DPCM_AUDIO] = { + .name = "Audio Port", + .stream_name = "Audio", + .cpu_dai_name = "media-cpu-dai", + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .platform_name = "sst-mfld-platform", + .nonatomic = true, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ops = &byt_cht_cx2072x_aif1_ops, + }, + [MERR_DPCM_DEEP_BUFFER] = { + .name = "Deep-Buffer Audio Port", + .stream_name = "Deep-Buffer Audio", + .cpu_dai_name = "deepbuffer-cpu-dai", + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .platform_name = "sst-mfld-platform", + .nonatomic = true, + .dynamic = 1, + .dpcm_playback = 1, + .ops = &byt_cht_cx2072x_aif1_ops, + }, + /* back ends */ + { + .name = "SSP2-Codec", + .id = 0, + .cpu_dai_name = "ssp2-port", + .platform_name = "sst-mfld-platform", + .no_pcm = 1, + .codec_dai_name = "cx2072x-hifi", + .codec_name = "i2c-14F10720:00", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .init = byt_cht_cx2072x_init, + .be_hw_params_fixup = byt_cht_cx2072x_fixup, + .nonatomic = true, + .dpcm_playback = 1, + .dpcm_capture = 1, + }, +}; + +/* SoC card */ +static struct snd_soc_card byt_cht_cx2072x_card = { + .name = "bytcht-cx2072x", + .owner = THIS_MODULE, + .dai_link = byt_cht_cx2072x_dais, + .num_links = ARRAY_SIZE(byt_cht_cx2072x_dais), + .dapm_widgets = byt_cht_cx2072x_widgets, + .num_dapm_widgets = ARRAY_SIZE(byt_cht_cx2072x_widgets), + .dapm_routes = byt_cht_cx2072x_audio_map, + .num_dapm_routes = ARRAY_SIZE(byt_cht_cx2072x_audio_map), + .controls = byt_cht_cx2072x_controls, + .num_controls = ARRAY_SIZE(byt_cht_cx2072x_controls), +}; + +static char codec_name[SND_ACPI_I2C_ID_LEN]; + +static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev) +{ + struct snd_soc_acpi_mach *mach; + struct acpi_device *adev; + int dai_index = 0; + int i, ret; + + byt_cht_cx2072x_card.dev = &pdev->dev; + mach = dev_get_platdata(&pdev->dev); + + /* fix index of codec dai */ + for (i = 0; i < ARRAY_SIZE(byt_cht_cx2072x_dais); i++) { + if (!strcmp(byt_cht_cx2072x_dais[i].codec_name, + "i2c-14F10720:00")) { + dai_index = i; + break; + } + } + + /* fixup codec name based on HID */ + adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); + if (adev) { + snprintf(codec_name, sizeof(codec_name), "i2c-%s", + acpi_dev_name(adev)); + put_device(&adev->dev); + byt_cht_cx2072x_dais[dai_index].codec_name = codec_name; + } + + /* override plaform name, if required */ + ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_cx2072x_card, + mach->mach_params.platform); + if (ret) + return ret; + + return devm_snd_soc_register_card(&pdev->dev, &byt_cht_cx2072x_card); +} + +static struct platform_driver snd_byt_cht_cx2072x_driver = { + .driver = { + .name = "bytcht_cx2072x", + }, + .probe = snd_byt_cht_cx2072x_probe, +}; +module_platform_driver(snd_byt_cht_cx2072x_driver); + +MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Machine driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:bytcht_cx2072x"); diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index 0cfab247876a..9cc7b17e0b10 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c @@ -217,6 +217,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[] = { .sof_fw_filename = "sof-byt.ri", .sof_tplg_filename = "sof-byt-max98090.tplg", }, + { + .id = "14F10720", + .drv_name = "bytcht_cx2072x", + .fw_filename = "intel/fw_sst_0f28.bin", + .board = "bytcht_cx2072x", + .sof_fw_filename = "sof-byt.ri", + .sof_tplg_filename = "sof-byt-cx2072x.tplg", + }, #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) /* * This is always last in the table so that it is selected only when diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c index ff9c31a39ad4..6d0755f1353a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c @@ -175,6 +175,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cherrytrail_machines[] = { .sof_fw_filename = "sof-cht.ri", .sof_tplg_filename = "sof-cht-rt5651.tplg", }, + { + .id = "14F10720", + .drv_name = "bytcht_cx2072x", + .fw_filename = "intel/fw_sst_22a8.bin", + .board = "bytcht_cx2072x", + .sof_fw_filename = "sof-cht.ri", + .sof_tplg_filename = "sof-cht-cx2072x.tplg", + }, #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) /* * This is always last in the table so that it is selected only when From 07ea238ca139aef1820802409a6a7bdd45e38caa Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 22 May 2019 23:17:03 +0900 Subject: [PATCH 067/626] ALSA: firewire-lib: use clear name for variable of CIP header This commit is to distinguish variable of CIP header from variable of isochronous context header. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index f43943fd962d..020edf2b1726 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -286,15 +286,15 @@ EXPORT_SYMBOL(amdtp_stream_set_parameters); unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) { unsigned int multiplier = 1; - unsigned int header_size = 0; + unsigned int cip_header_size = 0; if (s->flags & CIP_JUMBO_PAYLOAD) multiplier = 5; if (!(s->flags & CIP_NO_HEADER)) - header_size = 8; + cip_header_size = sizeof(__be32) * 2; - return header_size + - s->syt_interval * s->data_block_quadlets * 4 * multiplier; + return cip_header_size + + s->syt_interval * s->data_block_quadlets * sizeof(__be32) * multiplier; } EXPORT_SYMBOL(amdtp_stream_get_max_payload); From 6f3c07d03c6bc84d2da6ce0e24e9a1feece42c47 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 22 May 2019 23:17:04 +0900 Subject: [PATCH 068/626] ALSA: firewire-lib: calculate the length of packet payload in packet handler In current packet handler, the length of payload is given as an argument of callback function, however this value is just required to process payload of transferred isoc packet, thus just for IR context. This commit replaces the argument for payload of packet with the argument of context header. As a result, the length of payload is computed in packet handler for IR context. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 49 ++++++++++++++++------------------- sound/firewire/amdtp-stream.h | 5 ++-- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 020edf2b1726..4584525a7f30 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -474,14 +474,14 @@ static inline int queue_in_packet(struct amdtp_stream *s) return queue_packet(s, s->ctx_data.tx.max_payload_length); } -static int handle_out_packet(struct amdtp_stream *s, - unsigned int payload_length, unsigned int cycle, - unsigned int index) +static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, + const __be32 *ctx_header, unsigned int index) { __be32 *buffer; unsigned int syt; unsigned int data_blocks; unsigned int pcm_frames; + unsigned int payload_length; struct snd_pcm_substream *pcm; buffer = s->buffer.packets[s->packet_index].buffer; @@ -521,13 +521,14 @@ static int handle_out_packet(struct amdtp_stream *s, } static int handle_out_packet_without_header(struct amdtp_stream *s, - unsigned int payload_length, unsigned int cycle, - unsigned int index) + unsigned int cycle, const __be32 *ctx_header, + unsigned int index) { __be32 *buffer; unsigned int syt; unsigned int data_blocks; unsigned int pcm_frames; + unsigned int payload_length; struct snd_pcm_substream *pcm; buffer = s->buffer.packets[s->packet_index].buffer; @@ -551,11 +552,11 @@ static int handle_out_packet_without_header(struct amdtp_stream *s, return 0; } -static int handle_in_packet(struct amdtp_stream *s, - unsigned int payload_length, unsigned int cycle, - unsigned int index) +static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, + const __be32 *ctx_header, unsigned int index) { __be32 *buffer; + unsigned int payload_length; u32 cip_header[2]; unsigned int sph, fmt, fdf, syt; unsigned int data_block_quadlets, data_block_counter, dbc_interval; @@ -564,6 +565,14 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int pcm_frames; bool lost; + payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; + if (payload_length > s->ctx_data.tx.max_payload_length) { + dev_err(&s->unit->device, + "Detect jumbo payload: %04x %04x\n", + payload_length, s->ctx_data.tx.max_payload_length); + return -EIO; + } + buffer = s->buffer.packets[s->packet_index].buffer; cip_header[0] = be32_to_cpu(buffer[0]); cip_header[1] = be32_to_cpu(buffer[1]); @@ -668,14 +677,16 @@ end: } static int handle_in_packet_without_header(struct amdtp_stream *s, - unsigned int payload_length, unsigned int cycle, - unsigned int index) + unsigned int cycle, const __be32 *ctx_header, + unsigned int index) { __be32 *buffer; + unsigned int payload_length; unsigned int data_blocks; struct snd_pcm_substream *pcm; unsigned int pcm_frames; + payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; buffer = s->buffer.packets[s->packet_index].buffer; data_blocks = payload_length / sizeof(__be32) / s->data_block_quadlets; @@ -745,7 +756,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, cycle = compute_it_cycle(*ctx_header); - if (s->handle_packet(s, 0, cycle, i) < 0) { + if (s->handle_packet(s, cycle, ctx_header, i) < 0) { cancel_stream(s); return; } @@ -762,7 +773,6 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, { struct amdtp_stream *s = private_data; unsigned int i, packets; - unsigned int payload_length, max_payload_length; __be32 *ctx_header = header; if (s->packet_index < 0) @@ -771,25 +781,12 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, // The number of packets in buffer. packets = header_length / s->ctx_data.tx.ctx_header_size; - /* For buffer-over-run prevention. */ - max_payload_length = s->ctx_data.tx.max_payload_length; - for (i = 0; i < packets; i++) { - u32 iso_header = be32_to_cpu(ctx_header[0]); u32 cycle; cycle = compute_cycle_count(ctx_header[1]); - /* The number of bytes in this packet */ - payload_length = iso_header >> ISO_DATA_LENGTH_SHIFT; - if (payload_length > max_payload_length) { - dev_err(&s->unit->device, - "Detect jumbo payload: %04x %04x\n", - payload_length, max_payload_length); - break; - } - - if (s->handle_packet(s, payload_length, cycle, i) < 0) + if (s->handle_packet(s, cycle, ctx_header, i) < 0) break; ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 1945ef59ab92..d317fdc6ab5f 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -108,9 +108,8 @@ struct amdtp_stream { struct iso_packets_buffer buffer; int packet_index; int tag; - int (*handle_packet)(struct amdtp_stream *s, - unsigned int payload_quadlets, unsigned int cycle, - unsigned int index); + int (*handle_packet)(struct amdtp_stream *s, unsigned int cycle, + const __be32 *ctx_header, unsigned int index); union { struct { unsigned int ctx_header_size; From 8a400b999678996af6ca9434376b2260ec2ea9eb Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 22 May 2019 23:17:05 +0900 Subject: [PATCH 069/626] ALSA: firewire-lib: compute pointer to payload buffer in context handler The value of pointer to payload buffer is computed in each packet handler, however the pointer can be decided before call of packet handler. This commit adds an argument for the pointer to the packet handler to reduce codes to compute for the pointer. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 28 +++++++++++++--------------- sound/firewire/amdtp-stream.h | 3 ++- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 4584525a7f30..ab9dc7e9ffa4 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -475,16 +475,15 @@ static inline int queue_in_packet(struct amdtp_stream *s) } static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, - const __be32 *ctx_header, unsigned int index) + const __be32 *ctx_header, __be32 *buffer, + unsigned int index) { - __be32 *buffer; unsigned int syt; unsigned int data_blocks; unsigned int pcm_frames; unsigned int payload_length; struct snd_pcm_substream *pcm; - buffer = s->buffer.packets[s->packet_index].buffer; syt = calculate_syt(s, cycle); data_blocks = calculate_data_blocks(s, syt); pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); @@ -522,16 +521,14 @@ static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, static int handle_out_packet_without_header(struct amdtp_stream *s, unsigned int cycle, const __be32 *ctx_header, - unsigned int index) + __be32 *buffer, unsigned int index) { - __be32 *buffer; unsigned int syt; unsigned int data_blocks; unsigned int pcm_frames; unsigned int payload_length; struct snd_pcm_substream *pcm; - buffer = s->buffer.packets[s->packet_index].buffer; syt = calculate_syt(s, cycle); data_blocks = calculate_data_blocks(s, syt); pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); @@ -553,9 +550,9 @@ static int handle_out_packet_without_header(struct amdtp_stream *s, } static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, - const __be32 *ctx_header, unsigned int index) + const __be32 *ctx_header, __be32 *buffer, + unsigned int index) { - __be32 *buffer; unsigned int payload_length; u32 cip_header[2]; unsigned int sph, fmt, fdf, syt; @@ -573,7 +570,6 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, return -EIO; } - buffer = s->buffer.packets[s->packet_index].buffer; cip_header[0] = be32_to_cpu(buffer[0]); cip_header[1] = be32_to_cpu(buffer[1]); @@ -678,17 +674,15 @@ end: static int handle_in_packet_without_header(struct amdtp_stream *s, unsigned int cycle, const __be32 *ctx_header, - unsigned int index) + __be32 *buffer, unsigned int index) { - __be32 *buffer; unsigned int payload_length; unsigned int data_blocks; struct snd_pcm_substream *pcm; unsigned int pcm_frames; payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; - buffer = s->buffer.packets[s->packet_index].buffer; - data_blocks = payload_length / sizeof(__be32) / s->data_block_quadlets; + data_blocks = payload_length / 4 / s->data_block_quadlets; trace_amdtp_packet(s, cycle, NULL, payload_length, data_blocks, index); @@ -753,10 +747,12 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; ++i) { u32 cycle; + __be32 *buffer; cycle = compute_it_cycle(*ctx_header); + buffer = s->buffer.packets[s->packet_index].buffer; - if (s->handle_packet(s, cycle, ctx_header, i) < 0) { + if (s->handle_packet(s, cycle, ctx_header, buffer, i) < 0) { cancel_stream(s); return; } @@ -783,10 +779,12 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; i++) { u32 cycle; + __be32 *buffer; cycle = compute_cycle_count(ctx_header[1]); + buffer = s->buffer.packets[s->packet_index].buffer; - if (s->handle_packet(s, cycle, ctx_header, i) < 0) + if (s->handle_packet(s, cycle, ctx_header, buffer, i) < 0) break; ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index d317fdc6ab5f..5aa9683593d2 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -109,7 +109,8 @@ struct amdtp_stream { int packet_index; int tag; int (*handle_packet)(struct amdtp_stream *s, unsigned int cycle, - const __be32 *ctx_header, unsigned int index); + const __be32 *ctx_header, __be32 *buffer, + unsigned int index); union { struct { unsigned int ctx_header_size; From e335425b65965e6bebdf1ebc8187d6732ddaad00 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 22 May 2019 23:17:06 +0900 Subject: [PATCH 070/626] ALSA: firewire-lib: split helper function to check incoming CIP header A parser for CIP header in incoming packet is enough large. This commit splits it into a helper function to better looks of packet handler. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 100 ++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index ab9dc7e9ffa4..e9976a877944 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -549,29 +549,19 @@ static int handle_out_packet_without_header(struct amdtp_stream *s, return 0; } -static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, - const __be32 *ctx_header, __be32 *buffer, - unsigned int index) +static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, + unsigned int payload_length, + unsigned int *data_blocks, unsigned int *syt) { - unsigned int payload_length; u32 cip_header[2]; - unsigned int sph, fmt, fdf, syt; - unsigned int data_block_quadlets, data_block_counter, dbc_interval; - unsigned int data_blocks; - struct snd_pcm_substream *pcm; - unsigned int pcm_frames; + unsigned int sph; + unsigned int fmt; + unsigned int fdf; + unsigned int data_block_counter; bool lost; - payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; - if (payload_length > s->ctx_data.tx.max_payload_length) { - dev_err(&s->unit->device, - "Detect jumbo payload: %04x %04x\n", - payload_length, s->ctx_data.tx.max_payload_length); - return -EIO; - } - - cip_header[0] = be32_to_cpu(buffer[0]); - cip_header[1] = be32_to_cpu(buffer[1]); + cip_header[0] = be32_to_cpu(buf[0]); + cip_header[1] = be32_to_cpu(buf[1]); /* * This module supports 'Two-quadlet CIP header with SYT field'. @@ -583,9 +573,7 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, dev_info_ratelimited(&s->unit->device, "Invalid CIP header for AMDTP: %08X:%08X\n", cip_header[0], cip_header[1]); - data_blocks = 0; - pcm_frames = 0; - goto end; + return -EAGAIN; } /* Check valid protocol or not. */ @@ -595,19 +583,17 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, dev_info_ratelimited(&s->unit->device, "Detect unexpected protocol: %08x %08x\n", cip_header[0], cip_header[1]); - data_blocks = 0; - pcm_frames = 0; - goto end; + return -EAGAIN; } /* Calculate data blocks */ fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT; - if (payload_length < 12 || + if (payload_length < sizeof(__be32) * 2 || (fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) { - data_blocks = 0; + *data_blocks = 0; } else { - data_block_quadlets = - (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT; + unsigned int data_block_quadlets = + (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT; /* avoid division by zero */ if (data_block_quadlets == 0) { dev_err(&s->unit->device, @@ -618,13 +604,13 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, if (s->flags & CIP_WRONG_DBS) data_block_quadlets = s->data_block_quadlets; - data_blocks = (payload_length / 4 - 2) / + *data_blocks = (payload_length / sizeof(__be32) - 2) / data_block_quadlets; } /* Check data block counter continuity */ data_block_counter = cip_header[0] & CIP_DBC_MASK; - if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && + if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && s->data_block_counter != UINT_MAX) data_block_counter = s->data_block_counter; @@ -635,10 +621,12 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { lost = data_block_counter != s->data_block_counter; } else { - if (data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0) + unsigned int dbc_interval; + + if (*data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0) dbc_interval = s->ctx_data.tx.dbc_interval; else - dbc_interval = data_blocks; + dbc_interval = *data_blocks; lost = data_block_counter != ((s->data_block_counter + dbc_interval) & 0xff); @@ -651,16 +639,48 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, return -EIO; } + *syt = cip_header[1] & CIP_SYT_MASK; + + if (s->flags & CIP_DBC_IS_END_EVENT) { + s->data_block_counter = data_block_counter; + } else { + s->data_block_counter = + (data_block_counter + *data_blocks) & 0xff; + } + + return 0; +} + +static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, + const __be32 *ctx_header, __be32 *buffer, + unsigned int index) +{ + unsigned int payload_length; + unsigned int syt; + unsigned int data_blocks; + struct snd_pcm_substream *pcm; + unsigned int pcm_frames; + int err; + + payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; + if (payload_length > s->ctx_data.tx.max_payload_length) { + dev_err(&s->unit->device, + "Detect jumbo payload: %04x %04x\n", + payload_length, s->ctx_data.tx.max_payload_length); + return -EIO; + } + + err = check_cip_header(s, buffer, payload_length, &data_blocks, &syt); + if (err < 0) { + if (err != -EAGAIN) + return err; + pcm_frames = 0; + goto end; + } + trace_amdtp_packet(s, cycle, buffer, payload_length, data_blocks, index); - syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK; pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); - - if (s->flags & CIP_DBC_IS_END_EVENT) - s->data_block_counter = data_block_counter; - else - s->data_block_counter = - (data_block_counter + data_blocks) & 0xff; end: if (queue_in_packet(s) < 0) return -EIO; From f11453c7cc010d4052f630d541c39301b54cee3c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 22 May 2019 23:17:07 +0900 Subject: [PATCH 071/626] ALSA: firewire-lib: use 16 bytes IR context header to separate CIP header In IR context, some quadlets of packet payload can be included into context header. This is good for packet with CIP header because the context payload buffer can includes data blocks only for with-CIP and without-CIP pakets. This commit uses 16 bytes IR context header for this purpose. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 37 ++++++++++++++++++++++++----------- sound/firewire/amdtp-stream.h | 2 +- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index e9976a877944..fa99210f5a48 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -56,7 +56,10 @@ #define INTERRUPT_INTERVAL 16 #define QUEUE_LENGTH 48 -#define IR_HEADER_SIZE 8 // For header and timestamp. +// For iso header, tstamp and 2 CIP header. +#define IR_CTX_HEADER_SIZE_CIP 16 +// For iso header and tstamp. +#define IR_CTX_HEADER_SIZE_NO_CIP 8 #define HEADER_TSTAMP_MASK 0x0000ffff static void pcm_period_tasklet(unsigned long data); @@ -471,7 +474,7 @@ static inline int queue_out_packet(struct amdtp_stream *s, static inline int queue_in_packet(struct amdtp_stream *s) { - return queue_packet(s, s->ctx_data.tx.max_payload_length); + return queue_packet(s, s->ctx_data.tx.max_ctx_payload_length); } static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, @@ -656,6 +659,7 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, unsigned int index) { unsigned int payload_length; + const __be32 *cip_header; unsigned int syt; unsigned int data_blocks; struct snd_pcm_substream *pcm; @@ -663,14 +667,17 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, int err; payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; - if (payload_length > s->ctx_data.tx.max_payload_length) { + if (payload_length > s->ctx_data.tx.ctx_header_size + + s->ctx_data.tx.max_ctx_payload_length) { dev_err(&s->unit->device, "Detect jumbo payload: %04x %04x\n", - payload_length, s->ctx_data.tx.max_payload_length); + payload_length, s->ctx_data.tx.max_ctx_payload_length); return -EIO; } - err = check_cip_header(s, buffer, payload_length, &data_blocks, &syt); + cip_header = ctx_header + 2; + err = check_cip_header(s, cip_header, payload_length, &data_blocks, + &syt); if (err < 0) { if (err != -EAGAIN) return err; @@ -678,9 +685,10 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, goto end; } - trace_amdtp_packet(s, cycle, buffer, payload_length, data_blocks, index); + trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, + index); - pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); + pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); end: if (queue_in_packet(s) < 0) return -EIO; @@ -883,6 +891,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) [CIP_SFC_176400] = { 0, 67 }, }; unsigned int ctx_header_size; + unsigned int max_ctx_payload_size; enum dma_data_direction dir; int type, tag, err; @@ -909,14 +918,21 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) if (s->direction == AMDTP_IN_STREAM) { dir = DMA_FROM_DEVICE; type = FW_ISO_CONTEXT_RECEIVE; - ctx_header_size = IR_HEADER_SIZE; + if (!(s->flags & CIP_NO_HEADER)) + ctx_header_size = IR_CTX_HEADER_SIZE_CIP; + else + ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP; } else { dir = DMA_TO_DEVICE; type = FW_ISO_CONTEXT_TRANSMIT; ctx_header_size = 0; // No effect for IT context. } + + max_ctx_payload_size = amdtp_stream_get_max_payload(s) - + ctx_header_size; + err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, - amdtp_stream_get_max_payload(s), dir); + max_ctx_payload_size, dir); if (err < 0) goto err_unlock; @@ -934,8 +950,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) amdtp_stream_update(s); if (s->direction == AMDTP_IN_STREAM) { - s->ctx_data.tx.max_payload_length = - amdtp_stream_get_max_payload(s); + s->ctx_data.tx.max_ctx_payload_length = max_ctx_payload_size; s->ctx_data.tx.ctx_header_size = ctx_header_size; } diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 5aa9683593d2..234483a31df5 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -116,7 +116,7 @@ struct amdtp_stream { unsigned int ctx_header_size; // limit for payload of iso packet. - unsigned int max_payload_length; + unsigned int max_ctx_payload_length; // For quirks of CIP headers. // Fixed interval of dbc between previos/current From 947b437e1263c81bb5d30a84f1a4a35dbb9f6b78 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 22 May 2019 23:17:08 +0900 Subject: [PATCH 072/626] ALSA: firewire-lib: unify packet handler for IR context Usage of 16 bytes IR context header allows to handle context payload by the same code for with-CIP and without-CIP packets. This commit unifies both handlers of with-CIP and without-CIP packets. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 54 ++++++++++------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index fa99210f5a48..2d9c764061d1 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -676,13 +676,20 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, } cip_header = ctx_header + 2; - err = check_cip_header(s, cip_header, payload_length, &data_blocks, - &syt); - if (err < 0) { - if (err != -EAGAIN) - return err; - pcm_frames = 0; - goto end; + if (!(s->flags & CIP_NO_HEADER)) { + cip_header = &ctx_header[2]; + err = check_cip_header(s, cip_header, payload_length, + &data_blocks, &syt); + if (err < 0) { + if (err != -EAGAIN) + return err; + pcm_frames = 0; + goto end; + } + } else { + cip_header = NULL; + data_blocks = payload_length / 4 / s->data_block_quadlets; + syt = 0; } trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, @@ -700,33 +707,6 @@ end: return 0; } -static int handle_in_packet_without_header(struct amdtp_stream *s, - unsigned int cycle, const __be32 *ctx_header, - __be32 *buffer, unsigned int index) -{ - unsigned int payload_length; - unsigned int data_blocks; - struct snd_pcm_substream *pcm; - unsigned int pcm_frames; - - payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; - data_blocks = payload_length / 4 / s->data_block_quadlets; - - trace_amdtp_packet(s, cycle, NULL, payload_length, data_blocks, index); - - pcm_frames = s->process_data_blocks(s, buffer, data_blocks, NULL); - s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - - if (queue_in_packet(s) < 0) - return -EIO; - - pcm = READ_ONCE(s->pcm); - if (pcm && pcm_frames > 0) - update_pcm_pointers(s, pcm, pcm_frames); - - return 0; -} - // In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On // the other hand, in DMA descriptors of 1394 OHCI, 3 bits are used to represent // it. Thus, via Linux firewire subsystem, we can get the 3 bits for second. @@ -812,7 +792,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, cycle = compute_cycle_count(ctx_header[1]); buffer = s->buffer.packets[s->packet_index].buffer; - if (s->handle_packet(s, cycle, ctx_header, buffer, i) < 0) + if (handle_in_packet(s, cycle, ctx_header, buffer, i) < 0) break; ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); @@ -847,10 +827,6 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, cycle = compute_cycle_count(ctx_header[1]); context->callback.sc = in_stream_callback; - if (s->flags & CIP_NO_HEADER) - s->handle_packet = handle_in_packet_without_header; - else - s->handle_packet = handle_in_packet; } else { cycle = compute_it_cycle(*ctx_header); From 5463eb5c2f758069d1db21ed2cf23339431c9481 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Wed, 22 May 2019 22:52:04 +0800 Subject: [PATCH 073/626] ASoC: Mediatek: MT8183: enable dev runtime suspend and resume System suspend will power off audio, so we need regcache sync when system resume. Remove pm_runtime_get_sync in dev probe and pm_runtime_put_sync in dev remove.So that audio dev can triggle runitme suspend and resume. Signed-off-by: Jiaxin Yu Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index 56c37323bc13..4a31106d3471 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -1142,8 +1142,6 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) regcache_cache_only(afe->regmap, true); regcache_mark_dirty(afe->regmap); - pm_runtime_get_sync(&pdev->dev); - /* init memif */ afe->memif_size = MT8183_MEMIF_NUM; afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), @@ -1235,11 +1233,10 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) static int mt8183_afe_pcm_dev_remove(struct platform_device *pdev) { - pm_runtime_put_sync(&pdev->dev); - pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt8183_afe_runtime_suspend(&pdev->dev); + return 0; } From 108d0d40b932f80fc7f1dbd1de548d666e649a4b Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 22 May 2019 22:55:05 +0800 Subject: [PATCH 074/626] ASoC: mediatek: mt8183: remove unused DAPM pins Kernel emits the following messages when booting. ASoC: DAPM unknown pin Headset Mic ASoC: DAPM unknown pin Headphone Remove the unused DAPM pins. Signed-off-by: Tzung-Bi Shih Signed-off-by: Mark Brown --- .../soc/mediatek/mt8183/mt8183-da7219-max98357.c | 15 +-------------- .../mt8183/mt8183-mt6358-ts3a227-max98357.c | 16 +--------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 31ea8632c397..231fb49d79b9 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -18,18 +18,6 @@ static struct snd_soc_jack headset_jack; -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin headset_jack_pins[] = { - { - .pin = "Headphone", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - static struct snd_soc_dai_link_component mt8183_da7219_max98357_external_codecs[] = { { @@ -375,8 +363,7 @@ mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &headset_jack, - headset_jack_pins, - ARRAY_SIZE(headset_jack_pins)); + NULL, 0); if (ret) return ret; diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 4e44e5689d6f..1ba7aa58e4b6 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -17,19 +17,6 @@ static struct snd_soc_jack headset_jack; -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin headset_jack_pins[] = { - { - .pin = "Headphone", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, - -}; - static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -328,8 +315,7 @@ mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &headset_jack, - headset_jack_pins, - ARRAY_SIZE(headset_jack_pins)); + NULL, 0); if (ret) return ret; From 63ba8e4d04ab921f8aaa89227d2e0f7ad79725be Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 22 May 2019 22:54:02 +0800 Subject: [PATCH 075/626] ASoC: mediatek: mt8183: move card registration to the end of probe mt8183_mt6358_ts3a227_max98357_dev_probe() does not return immediately if devm_snd_soc_register_card() returns fail. As a result, the rest of code still get executed. Two options to fix: 1. add an extra return statement if devm_snd_soc_register_card() returns fail 2. move devm_snd_soc_register_card() to the end of probe Adopt option 2 which is more clear and common. Signed-off-by: Tzung-Bi Shih Signed-off-by: Mark Brown --- .../soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 1ba7aa58e4b6..23c422f13808 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -331,7 +331,7 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) struct device_node *platform_node; struct snd_soc_dai_link *dai_link; struct pinctrl *default_pins; - int ret, i; + int i; card->dev = &pdev->dev; @@ -366,11 +366,6 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) return -EINVAL; } - ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) - dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", - __func__, ret); - default_pins = devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT); if (IS_ERR(default_pins)) { @@ -379,7 +374,7 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) return PTR_ERR(default_pins); } - return ret; + return devm_snd_soc_register_card(&pdev->dev, card); } #ifdef CONFIG_OF From 92bfa664ae133d13a3496f71f5c7c7f4d4827a88 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 May 2019 15:29:17 -0500 Subject: [PATCH 076/626] ALSA: pcm: oss: Use struct_size() helper Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes, in particular in the context in which this code is being used. So, replace the following form: sizeof(struct rate_priv) + src_format->channels * sizeof(struct rate_channel) with: struct_size(data, channels, src_format->channels) This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/core/oss/rate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c index 2fa9299a440d..7cd09cef6961 100644 --- a/sound/core/oss/rate.c +++ b/sound/core/oss/rate.c @@ -323,8 +323,8 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug, err = snd_pcm_plugin_build(plug, "rate conversion", src_format, dst_format, - sizeof(struct rate_priv) + - src_format->channels * sizeof(struct rate_channel), + struct_size(data, channels, + src_format->channels), &plugin); if (err < 0) return err; From e4e07c6cdca8a837ab40363fc8002cf62965a628 Mon Sep 17 00:00:00 2001 From: Philippe Bekaert Date: Thu, 23 May 2019 23:56:49 +0200 Subject: [PATCH 077/626] ALSA: hdspm: Fix single speed ADAT capture and playback with RME HDSPe AIO By taking into account the mapping from logical to DMA channels when enabling or disabling audio channels, ADAT channels 3 to 8 on the RME HDSPe AIO card are now correctly captured and played back in single speed mode. Since the mapping is an identity mapping for all cards except AIO and RayDAT, only those cards should be affected by this patch. It was tested on an AIO card. The patch needs testing on other cards, in particular RayDAT. Note: this patch does not solve ADAT capture and playback issues in double or triple speed mode. That seems to be another problem. Signed-off-by: Philippe Bekaert Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 59 +++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 1209cf0b05e0..982b297b3d0a 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -23,6 +23,9 @@ * * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth * + * Modified 2019-05-23 fix AIO single speed ADAT capture and playback + * by Philippe.Bekaert@uhasselt.be + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -1105,9 +1108,9 @@ static int hdspm_autosync_ref(struct hdspm *hdspm); static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out); static int snd_hdspm_set_defaults(struct hdspm *hdspm); static int hdspm_system_clock_mode(struct hdspm *hdspm); -static void hdspm_set_sgbuf(struct hdspm *hdspm, - struct snd_pcm_substream *substream, - unsigned int reg, int channels); +static void hdspm_set_channel_dma_addr(struct hdspm *hdspm, + struct snd_pcm_substream *substream, + unsigned int reg, int channels); static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx); static int hdspm_wc_sync_check(struct hdspm *hdspm); @@ -5588,11 +5591,16 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut, - params_channels(params)); + for (i = 0; i < params_channels(params); ++i) { + int c = hdspm->channel_map_out[i]; - for (i = 0; i < params_channels(params); ++i) - snd_hdspm_enable_out(hdspm, i, 1); + if (c < 0) + continue; /* just make sure */ + hdspm_set_channel_dma_addr(hdspm, substream, + HDSPM_pageAddressBufferOut, + c); + snd_hdspm_enable_out(hdspm, c, 1); + } hdspm->playback_buffer = (unsigned char *) substream->runtime->dma_area; @@ -5600,11 +5608,16 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, "Allocated sample buffer for playback at %p\n", hdspm->playback_buffer); } else { - hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn, - params_channels(params)); + for (i = 0; i < params_channels(params); ++i) { + int c = hdspm->channel_map_in[i]; - for (i = 0; i < params_channels(params); ++i) - snd_hdspm_enable_in(hdspm, i, 1); + if (c < 0) + continue; + hdspm_set_channel_dma_addr(hdspm, substream, + HDSPM_pageAddressBufferIn, + c); + snd_hdspm_enable_in(hdspm, c, 1); + } hdspm->capture_buffer = (unsigned char *) substream->runtime->dma_area; @@ -5665,19 +5678,17 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream) struct hdspm *hdspm = snd_pcm_substream_chip(substream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - - /* params_channels(params) should be enough, - but to get sure in case of error */ - for (i = 0; i < hdspm->max_channels_out; ++i) + /* Just disable all channels. The saving when disabling a */ + /* smaller set is not worth the trouble. */ + for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) snd_hdspm_enable_out(hdspm, i, 0); hdspm->playback_buffer = NULL; } else { - for (i = 0; i < hdspm->max_channels_in; ++i) + for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) snd_hdspm_enable_in(hdspm, i, 0); hdspm->capture_buffer = NULL; - } snd_pcm_lib_free_pages(substream); @@ -6416,17 +6427,17 @@ static int snd_hdspm_preallocate_memory(struct hdspm *hdspm) return 0; } - -static void hdspm_set_sgbuf(struct hdspm *hdspm, - struct snd_pcm_substream *substream, - unsigned int reg, int channels) +/* Inform the card what DMA addresses to use for the indicated channel. */ +/* Each channel got 16 4K pages allocated for DMA transfers. */ +static void hdspm_set_channel_dma_addr(struct hdspm *hdspm, + struct snd_pcm_substream *substream, + unsigned int reg, int channel) { int i; - /* continuous memory segment */ - for (i = 0; i < (channels * 16); i++) + for (i = channel * 16; i < channel * 16 + 16; i++) hdspm_write(hdspm, reg + 4 * i, - snd_pcm_sgbuf_get_addr(substream, 4096 * i)); + snd_pcm_sgbuf_get_addr(substream, 4096 * i)); } From 252219c7b38c76b0da374d5197cc825772fd487d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 24 May 2019 00:14:37 +0900 Subject: [PATCH 078/626] ALSA: firewire-lib: split helper function to generate CIP header This is minor code refactoring to split a function to generate CIP header. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 2d9c764061d1..25985663bb2b 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -477,6 +477,19 @@ static inline int queue_in_packet(struct amdtp_stream *s) return queue_packet(s, s->ctx_data.tx.max_ctx_payload_length); } +static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], + unsigned int syt) +{ + cip_header[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) | + (s->data_block_quadlets << CIP_DBS_SHIFT) | + ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | + s->data_block_counter); + cip_header[1] = cpu_to_be32(CIP_EOH | + ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | + ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | + (syt & CIP_SYT_MASK)); +} + static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, const __be32 *ctx_header, __be32 *buffer, unsigned int index) @@ -495,14 +508,7 @@ static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - buffer[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) | - (s->data_block_quadlets << CIP_DBS_SHIFT) | - ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | - s->data_block_counter); - buffer[1] = cpu_to_be32(CIP_EOH | - ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | - ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | - (syt & CIP_SYT_MASK)); + generate_cip_header(s, buffer, syt); if (!(s->flags & CIP_DBC_IS_END_EVENT)) s->data_block_counter = From 16be458993be75ca255cee176df47955608b4df8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 24 May 2019 00:14:38 +0900 Subject: [PATCH 079/626] ALSA: firewire-lib: unify packet handler for IT context The handlers for packet with CIP and without CIP include common codes. This commit unifies them and remove an member for pointer to callback function from data structure. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 59 +++++++++++------------------------ sound/firewire/amdtp-stream.h | 3 -- 2 files changed, 18 insertions(+), 44 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 25985663bb2b..b11a8d244f89 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -496,26 +496,38 @@ static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, { unsigned int syt; unsigned int data_blocks; - unsigned int pcm_frames; unsigned int payload_length; + __be32 *cip_header; + unsigned int pcm_frames; struct snd_pcm_substream *pcm; syt = calculate_syt(s, cycle); data_blocks = calculate_data_blocks(s, syt); - pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); + + payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; + if (!(s->flags & CIP_NO_HEADER)) { + cip_header = buffer; + buffer += 2; + payload_length += 2 * sizeof(__be32); + } else { + cip_header = NULL; + } + + pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); if (s->flags & CIP_DBC_IS_END_EVENT) s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - generate_cip_header(s, buffer, syt); + if (cip_header) + generate_cip_header(s, cip_header, syt); if (!(s->flags & CIP_DBC_IS_END_EVENT)) s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; - trace_amdtp_packet(s, cycle, buffer, payload_length, data_blocks, index); + trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, + index); if (queue_out_packet(s, payload_length) < 0) return -EIO; @@ -524,37 +536,6 @@ static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, if (pcm && pcm_frames > 0) update_pcm_pointers(s, pcm, pcm_frames); - /* No need to return the number of handled data blocks. */ - return 0; -} - -static int handle_out_packet_without_header(struct amdtp_stream *s, - unsigned int cycle, const __be32 *ctx_header, - __be32 *buffer, unsigned int index) -{ - unsigned int syt; - unsigned int data_blocks; - unsigned int pcm_frames; - unsigned int payload_length; - struct snd_pcm_substream *pcm; - - syt = calculate_syt(s, cycle); - data_blocks = calculate_data_blocks(s, syt); - pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); - s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - - payload_length = data_blocks * 4 * s->data_block_quadlets; - - trace_amdtp_packet(s, cycle, NULL, payload_length, data_blocks, index); - - if (queue_out_packet(s, payload_length) < 0) - return -EIO; - - pcm = READ_ONCE(s->pcm); - if (pcm && pcm_frames > 0) - update_pcm_pointers(s, pcm, pcm_frames); - - /* No need to return the number of handled data blocks. */ return 0; } @@ -766,7 +747,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, cycle = compute_it_cycle(*ctx_header); buffer = s->buffer.packets[s->packet_index].buffer; - if (s->handle_packet(s, cycle, ctx_header, buffer, i) < 0) { + if (handle_out_packet(s, cycle, ctx_header, buffer, i) < 0) { cancel_stream(s); return; } @@ -837,10 +818,6 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, cycle = compute_it_cycle(*ctx_header); context->callback.sc = out_stream_callback; - if (s->flags & CIP_NO_HEADER) - s->handle_packet = handle_out_packet_without_header; - else - s->handle_packet = handle_out_packet; } s->start_cycle = cycle; diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 234483a31df5..3942894c11ac 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -108,9 +108,6 @@ struct amdtp_stream { struct iso_packets_buffer buffer; int packet_index; int tag; - int (*handle_packet)(struct amdtp_stream *s, unsigned int cycle, - const __be32 *ctx_header, __be32 *buffer, - unsigned int index); union { struct { unsigned int ctx_header_size; From 6007bf5460cc3b6c63feed5084047b9cc2517eb0 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 24 May 2019 00:14:39 +0900 Subject: [PATCH 080/626] ALSA: firewire-lib: code refactoring to queueing packets This commit is a preparation to queue IT packet with header. To enable packet handler to fill the header, this commit uses kernel stack for data structure of packet parameter in several part of this file. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 54 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index b11a8d244f89..e813d31ff2ad 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -430,30 +430,15 @@ static void pcm_period_tasklet(unsigned long data) snd_pcm_period_elapsed(pcm); } -static int queue_packet(struct amdtp_stream *s, unsigned int payload_length) +static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params) { - struct fw_iso_packet p = {0}; - int err = 0; + int err; - if (IS_ERR(s->context)) - goto end; + params->interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); + params->tag = s->tag; + params->sy = 0; - p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); - p.tag = s->tag; - - if (s->direction == AMDTP_IN_STREAM) { - // Queue one packet for IR context. - p.header_length = s->ctx_data.tx.ctx_header_size; - } else { - // No header for this packet. - p.header_length = 0; - } - - if (payload_length > 0) - p.payload_length = payload_length; - else - p.skip = true; - err = fw_iso_context_queue(s->context, &p, &s->buffer.iso_buffer, + err = fw_iso_context_queue(s->context, params, &s->buffer.iso_buffer, s->buffer.packets[s->packet_index].offset); if (err < 0) { dev_err(&s->unit->device, "queueing error: %d\n", err); @@ -467,14 +452,24 @@ end: } static inline int queue_out_packet(struct amdtp_stream *s, + struct fw_iso_packet *params, unsigned int payload_length) { - return queue_packet(s, payload_length); + // No header for this packet. + params->header_length = 0; + params->payload_length = payload_length; + params->skip = !!(payload_length == 0); + return queue_packet(s, params); } -static inline int queue_in_packet(struct amdtp_stream *s) +static inline int queue_in_packet(struct amdtp_stream *s, + struct fw_iso_packet *params) { - return queue_packet(s, s->ctx_data.tx.max_ctx_payload_length); + // Queue one packet for IR context. + params->header_length = s->ctx_data.tx.ctx_header_size; + params->payload_length = s->ctx_data.tx.max_ctx_payload_length; + params->skip = false; + return queue_packet(s, params); } static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], @@ -500,6 +495,7 @@ static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, __be32 *cip_header; unsigned int pcm_frames; struct snd_pcm_substream *pcm; + struct fw_iso_packet params = {0}; syt = calculate_syt(s, cycle); data_blocks = calculate_data_blocks(s, syt); @@ -529,7 +525,7 @@ static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, index); - if (queue_out_packet(s, payload_length) < 0) + if (queue_out_packet(s, ¶ms, payload_length) < 0) return -EIO; pcm = READ_ONCE(s->pcm); @@ -651,6 +647,7 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, unsigned int data_blocks; struct snd_pcm_substream *pcm; unsigned int pcm_frames; + struct fw_iso_packet params = {0}; int err; payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; @@ -684,7 +681,7 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); end: - if (queue_in_packet(s) < 0) + if (queue_in_packet(s, ¶ms) < 0) return -EIO; pcm = READ_ONCE(s->pcm); @@ -920,10 +917,11 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) s->packet_index = 0; do { + struct fw_iso_packet params; if (s->direction == AMDTP_IN_STREAM) - err = queue_in_packet(s); + err = queue_in_packet(s, ¶ms); else - err = queue_out_packet(s, 0); + err = queue_out_packet(s, ¶ms, 0); if (err < 0) goto err_context; } while (s->packet_index > 0); From b18f0cfaf16bee36bc4d3cab6771c7d74ed472ac Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 24 May 2019 00:14:40 +0900 Subject: [PATCH 081/626] ALSA: firewire-lib: use 8 byte packet header for IT context to separate CIP header from CIP payload In Linux firewire subsystem, for IT context, some quadlets of isochronous packet payload can be indicated as a part of packet header to queue to the context. This commit uses the packet header to split CIP headers from CIP payload. As a result, regardless of CIP or non-CIP, context payload includes data blocks only. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 63 +++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index e813d31ff2ad..791efa5585c2 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -62,6 +62,9 @@ #define IR_CTX_HEADER_SIZE_NO_CIP 8 #define HEADER_TSTAMP_MASK 0x0000ffff +#define IT_PKT_HEADER_SIZE_CIP 8 // For 2 CIP header. +#define IT_PKT_HEADER_SIZE_NO_CIP 0 // Nothing. + static void pcm_period_tasklet(unsigned long data); /** @@ -452,13 +455,10 @@ end: } static inline int queue_out_packet(struct amdtp_stream *s, - struct fw_iso_packet *params, - unsigned int payload_length) + struct fw_iso_packet *params) { - // No header for this packet. - params->header_length = 0; - params->payload_length = payload_length; - params->skip = !!(payload_length == 0); + params->skip = + !!(params->header_length == 0 && params->payload_length == 0); return queue_packet(s, params); } @@ -491,41 +491,41 @@ static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, { unsigned int syt; unsigned int data_blocks; - unsigned int payload_length; __be32 *cip_header; unsigned int pcm_frames; struct snd_pcm_substream *pcm; - struct fw_iso_packet params = {0}; + struct { + struct fw_iso_packet params; + __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; + } template = { {0}, {0} }; syt = calculate_syt(s, cycle); data_blocks = calculate_data_blocks(s, syt); - - payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; - if (!(s->flags & CIP_NO_HEADER)) { - cip_header = buffer; - buffer += 2; - payload_length += 2 * sizeof(__be32); - } else { - cip_header = NULL; - } - pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); if (s->flags & CIP_DBC_IS_END_EVENT) s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - if (cip_header) + if (!(s->flags & CIP_NO_HEADER)) { + cip_header = (__be32 *)template.params.header; generate_cip_header(s, cip_header, syt); + template.params.header_length = 2 * sizeof(__be32); + } else { + cip_header = NULL; + } if (!(s->flags & CIP_DBC_IS_END_EVENT)) s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, - index); + template.params.payload_length = + data_blocks * sizeof(__be32) * s->data_block_quadlets; - if (queue_out_packet(s, ¶ms, payload_length) < 0) + trace_amdtp_packet(s, cycle, cip_header, template.params.payload_length, + data_blocks, index); + + if (queue_out_packet(s, &template.params) < 0) return -EIO; pcm = READ_ONCE(s->pcm); @@ -878,14 +878,18 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) ctx_header_size = IR_CTX_HEADER_SIZE_CIP; else ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP; + + max_ctx_payload_size = amdtp_stream_get_max_payload(s) - + ctx_header_size; } else { dir = DMA_TO_DEVICE; type = FW_ISO_CONTEXT_TRANSMIT; ctx_header_size = 0; // No effect for IT context. - } - max_ctx_payload_size = amdtp_stream_get_max_payload(s) - - ctx_header_size; + max_ctx_payload_size = amdtp_stream_get_max_payload(s); + if (!(s->flags & CIP_NO_HEADER)) + max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP; + } err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, max_ctx_payload_size, dir); @@ -918,10 +922,13 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) s->packet_index = 0; do { struct fw_iso_packet params; - if (s->direction == AMDTP_IN_STREAM) + if (s->direction == AMDTP_IN_STREAM) { err = queue_in_packet(s, ¶ms); - else - err = queue_out_packet(s, ¶ms, 0); + } else { + params.header_length = 0; + params.payload_length = 0; + err = queue_out_packet(s, ¶ms); + } if (err < 0) goto err_context; } while (s->packet_index > 0); From 3c194923154132836d143d9ba37f5ee94d790c75 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 24 May 2019 18:03:39 +0900 Subject: [PATCH 082/626] ALSA: firewire-lib: fix data block counter for incoming packet without CIP header The value of data block counter is not calculated for incoming packet without CIP header. This commit fixes the bug. Fixes: 947b437e1263 ("ALSA: firewire-lib: unify packet handler for IR context") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 791efa5585c2..8a7da86650ea 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -674,6 +674,8 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, cip_header = NULL; data_blocks = payload_length / 4 / s->data_block_quadlets; syt = 0; + s->data_block_counter = + (s->data_block_counter + data_blocks) & 0xff; } trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, From e703965a129cdd72ff74e248f8fbf0d617844527 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 24 May 2019 18:03:40 +0900 Subject: [PATCH 083/626] ALSA: firewire-lib: fix inverted node IDs for amdtp_packet events The amdtp_packet events have inverted node IDs for src/dst. This commit fixes the bug. Fixes: 8d3f1fdf5211 ("ALSA: firewire-lib: unify tracing events to 'amdtp_packet' event") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream-trace.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index ab708857979f..5fe0920f04e5 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -35,11 +35,11 @@ TRACE_EVENT(amdtp_packet, __entry->cycle = cycles % CYCLES_PER_SECOND; __entry->channel = s->context->channel; if (s->direction == AMDTP_IN_STREAM) { - __entry->src = fw_parent_device(s->unit)->node_id; - __entry->dest = fw_parent_device(s->unit)->card->node_id; - } else { __entry->src = fw_parent_device(s->unit)->card->node_id; __entry->dest = fw_parent_device(s->unit)->node_id; + } else { + __entry->src = fw_parent_device(s->unit)->node_id; + __entry->dest = fw_parent_device(s->unit)->card->node_id; } if (cip_header) { memcpy(__get_dynamic_array(cip_header), cip_header, From 6bc1a2699b79d7449de3bdd9cfe704e5d698acff Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 24 May 2019 18:03:41 +0900 Subject: [PATCH 084/626] ALSA: firewire-lib: refactoring to obsolete IT packet handler As a result of heavy refactoring based on IT packet header, the packet handler becomes simpler. This commit merges the packet handler into function for IT context callback. The logic to build IT packet header and tracepoints event is split to a function. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 62 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 8a7da86650ea..03ed2757dfc8 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -485,54 +485,36 @@ static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], (syt & CIP_SYT_MASK)); } -static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle, - const __be32 *ctx_header, __be32 *buffer, - unsigned int index) +static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, + struct fw_iso_packet *params, + unsigned int data_blocks, unsigned int syt, + unsigned int index) { - unsigned int syt; - unsigned int data_blocks; __be32 *cip_header; - unsigned int pcm_frames; - struct snd_pcm_substream *pcm; - struct { - struct fw_iso_packet params; - __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; - } template = { {0}, {0} }; - syt = calculate_syt(s, cycle); - data_blocks = calculate_data_blocks(s, syt); - pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); - - if (s->flags & CIP_DBC_IS_END_EVENT) + if (s->flags & CIP_DBC_IS_END_EVENT) { s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; + } if (!(s->flags & CIP_NO_HEADER)) { - cip_header = (__be32 *)template.params.header; + cip_header = (__be32 *)params->header; generate_cip_header(s, cip_header, syt); - template.params.header_length = 2 * sizeof(__be32); + params->header_length = 2 * sizeof(__be32); } else { cip_header = NULL; } - if (!(s->flags & CIP_DBC_IS_END_EVENT)) + if (!(s->flags & CIP_DBC_IS_END_EVENT)) { s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; + } - template.params.payload_length = + params->payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; - trace_amdtp_packet(s, cycle, cip_header, template.params.payload_length, + trace_amdtp_packet(s, cycle, cip_header, params->payload_length, data_blocks, index); - - if (queue_out_packet(s, &template.params) < 0) - return -EIO; - - pcm = READ_ONCE(s->pcm); - if (pcm && pcm_frames > 0) - update_pcm_pointers(s, pcm, pcm_frames); - - return 0; } static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, @@ -741,16 +723,34 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; ++i) { u32 cycle; + unsigned int syt; + unsigned int data_block; __be32 *buffer; + unsigned int pcm_frames; + struct { + struct fw_iso_packet params; + __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; + } template = { {0}, {0} }; + struct snd_pcm_substream *pcm; cycle = compute_it_cycle(*ctx_header); + syt = calculate_syt(s, cycle); + data_block = calculate_data_blocks(s, syt); buffer = s->buffer.packets[s->packet_index].buffer; + pcm_frames = s->process_data_blocks(s, buffer, data_block, &syt); - if (handle_out_packet(s, cycle, ctx_header, buffer, i) < 0) { + build_it_pkt_header(s, cycle, &template.params, data_block, syt, + i); + + if (queue_out_packet(s, &template.params) < 0) { cancel_stream(s); return; } + pcm = READ_ONCE(s->pcm); + if (pcm && pcm_frames > 0) + update_pcm_pointers(s, pcm, pcm_frames); + ++ctx_header; } From 98e3e43b599d742c104864c6772a251025ffb52b Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 24 May 2019 18:03:42 +0900 Subject: [PATCH 085/626] ALSA: firewire-lib: refactoring to obsolete IR packet handler As a result of heavy refactoring based on IR context header, the packet handler becomes simpler. This commit merges the packet handler into function for IR context callback. The logic to parse IR context header and tracepoints event is split to a function. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 78 ++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 03ed2757dfc8..3aef6a78a188 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -619,59 +619,42 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, return 0; } -static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle, - const __be32 *ctx_header, __be32 *buffer, - unsigned int index) +static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, + const __be32 *ctx_header, + unsigned int *payload_length, + unsigned int *data_blocks, + unsigned int *syt, unsigned int index) { - unsigned int payload_length; const __be32 *cip_header; - unsigned int syt; - unsigned int data_blocks; - struct snd_pcm_substream *pcm; - unsigned int pcm_frames; - struct fw_iso_packet params = {0}; int err; - payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; - if (payload_length > s->ctx_data.tx.ctx_header_size + + *payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; + if (*payload_length > s->ctx_data.tx.ctx_header_size + s->ctx_data.tx.max_ctx_payload_length) { dev_err(&s->unit->device, "Detect jumbo payload: %04x %04x\n", - payload_length, s->ctx_data.tx.max_ctx_payload_length); + *payload_length, s->ctx_data.tx.max_ctx_payload_length); return -EIO; } - cip_header = ctx_header + 2; if (!(s->flags & CIP_NO_HEADER)) { - cip_header = &ctx_header[2]; - err = check_cip_header(s, cip_header, payload_length, - &data_blocks, &syt); - if (err < 0) { - if (err != -EAGAIN) - return err; - pcm_frames = 0; - goto end; - } + cip_header = ctx_header + 2; + err = check_cip_header(s, cip_header, *payload_length, + data_blocks, syt); + if (err < 0) + return err; } else { cip_header = NULL; - data_blocks = payload_length / 4 / s->data_block_quadlets; - syt = 0; + *data_blocks = *payload_length / sizeof(__be32) / + s->data_block_quadlets; + *syt = 0; s->data_block_counter = - (s->data_block_counter + data_blocks) & 0xff; + (s->data_block_counter + *data_blocks) & 0xff; } - trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, + trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, index); - pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); -end: - if (queue_in_packet(s, ¶ms) < 0) - return -EIO; - - pcm = READ_ONCE(s->pcm); - if (pcm && pcm_frames > 0) - update_pcm_pointers(s, pcm, pcm_frames); - return 0; } @@ -773,13 +756,32 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; i++) { u32 cycle; + unsigned int payload_length; + unsigned int data_block; + unsigned int syt; __be32 *buffer; + unsigned int pcm_frames = 0; + struct fw_iso_packet params = {0}; + struct snd_pcm_substream *pcm; + int err; cycle = compute_cycle_count(ctx_header[1]); - buffer = s->buffer.packets[s->packet_index].buffer; - - if (handle_in_packet(s, cycle, ctx_header, buffer, i) < 0) + err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, + &data_block, &syt, i); + if (err < 0 && err != -EAGAIN) break; + if (err >= 0) { + buffer = s->buffer.packets[s->packet_index].buffer; + pcm_frames = s->process_data_blocks(s, buffer, + data_block, &syt); + } + + if (queue_in_packet(s, ¶ms) < 0) + break; + + pcm = READ_ONCE(s->pcm); + if (pcm && pcm_frames > 0) + update_pcm_pointers(s, pcm, pcm_frames); ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); } From b8bb535ae43ac42588a26d0781cb0f8360269dd5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 23 May 2019 18:39:46 -0500 Subject: [PATCH 086/626] ASoC: Intel: boards: remove unnecessary inclusion of skl.h We've used a standard interface for machine drivers for some time now, there is no need for this dependency on a Skylake-specific header Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/glk_rt5682_max98357a.c | 1 - sound/soc/intel/boards/kbl_da7219_max98357a.c | 1 - sound/soc/intel/boards/kbl_da7219_max98927.c | 1 - sound/soc/intel/boards/skl_hda_dsp_common.c | 1 - 4 files changed, 4 deletions(-) diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index 6b677b5bcdcd..7180100a9084 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -17,7 +17,6 @@ #include #include #include -#include "../skylake/skl.h" #include "../../codecs/rt5682.h" #include "../../codecs/hdac_hdmi.h" diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index 07491a0f8fb8..4e5db2241fb9 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -19,7 +19,6 @@ #include #include "../../codecs/da7219.h" #include "../../codecs/hdac_hdmi.h" -#include "../skylake/skl.h" #include "../../codecs/da7219-aad.h" #define KBL_DIALOG_CODEC_DAI "da7219-hifi" diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index 1efe7fdad2cb..d6765c359449 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -19,7 +19,6 @@ #include #include "../../codecs/da7219.h" #include "../../codecs/hdac_hdmi.h" -#include "../skylake/skl.h" #include "../../codecs/da7219-aad.h" #define KBL_DIALOG_CODEC_DAI "da7219-hifi" diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c index 8b68f41a5b88..82f10bf2abb2 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.c +++ b/sound/soc/intel/boards/skl_hda_dsp_common.c @@ -12,7 +12,6 @@ #include #include #include "../../codecs/hdac_hdmi.h" -#include "../skylake/skl.h" #include "skl_hda_dsp_common.h" #define NAME_SIZE 32 From 07597910a9c02c0ce33b779b5c24c5407ee7bd48 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 May 2019 15:36:37 -0500 Subject: [PATCH 087/626] ASoC: dapm: Use struct_size() in krealloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = krealloc(instance, sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, use the new struct_size() helper: instance = krealloc(instance, struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b71ddaca70e5..511ed84b147b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -487,7 +487,8 @@ static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol, n = 1; new_wlist = krealloc(data->wlist, - sizeof(*new_wlist) + sizeof(widget) * n, GFP_KERNEL); + struct_size(new_wlist, widgets, n), + GFP_KERNEL); if (!new_wlist) return -ENOMEM; From d00cc2f16a41ee704113f9447f2d0a10ad4f0ec7 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 May 2019 17:23:33 -0500 Subject: [PATCH 088/626] ASoC: Intel: Skylake: Use struct_size() helper Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes, in particular in the context in which this code is being used. So, replace the following form: uuid_params->num_modules * sizeof(struct skl_mod_inst_map) + sizeof(uuid_params->num_modules) with: struct_size(params, u.map, uuid_params->num_modules) and so on... This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 389f1862bc43..c69d999d7bf1 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -941,9 +941,7 @@ static int skl_tplg_find_moduleid_from_uuid(struct skl *skl, if (bc->set_params == SKL_PARAM_BIND && bc->max) { uuid_params = (struct skl_kpb_params *)bc->params; - size = uuid_params->num_modules * - sizeof(struct skl_mod_inst_map) + - sizeof(uuid_params->num_modules); + size = struct_size(params, u.map, uuid_params->num_modules); params = devm_kzalloc(bus->dev, size, GFP_KERNEL); if (!params) @@ -3315,7 +3313,7 @@ static int skl_tplg_get_int_tkn(struct device *dev, struct snd_soc_tplg_vendor_value_elem *tkn_elem, struct skl *skl) { - int tkn_count = 0, ret, size; + int tkn_count = 0, ret; static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; struct skl_module_res *res = NULL; struct skl_module_iface *fmt = NULL; @@ -3323,6 +3321,7 @@ static int skl_tplg_get_int_tkn(struct device *dev, static struct skl_astate_param *astate_table; static int astate_cfg_idx, count; int i; + size_t size; if (skl->modules) { mod = skl->modules[mod_idx]; @@ -3366,8 +3365,8 @@ static int skl_tplg_get_int_tkn(struct device *dev, return -EINVAL; } - size = tkn_elem->value * sizeof(struct skl_astate_param) + - sizeof(count); + size = struct_size(skl->cfg.astate_cfg, astate_table, + tkn_elem->value); skl->cfg.astate_cfg = devm_kzalloc(dev, size, GFP_KERNEL); if (!skl->cfg.astate_cfg) return -ENOMEM; From e718a3eb09ae491147ded7e2e923ba6de59f0b24 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 May 2019 11:07:48 -0500 Subject: [PATCH 089/626] ASoC: qdsp6: q6core: Use struct_size() in kmemdup() Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes, in particular in the context in which this code is being used. So, replace code of the following form: sizeof(*fwk) + fwk->num_services * sizeof(fwk->svc_api_info[0]); with: struct_size(fwk, svc_api_info, fwk->num_services) and so on... Notice that variables bytes and len are unnecessary, hence they are removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6core.c b/sound/soc/qcom/qdsp6/q6core.c index cdfc8ab6cfc0..ae314a652efe 100644 --- a/sound/soc/qcom/qdsp6/q6core.c +++ b/sound/soc/qcom/qdsp6/q6core.c @@ -98,13 +98,13 @@ static int q6core_callback(struct apr_device *adev, struct apr_resp_pkt *data) } case AVCS_CMDRSP_GET_FWK_VERSION: { struct avcs_cmdrsp_get_fwk_version *fwk; - int bytes; fwk = data->payload; - bytes = sizeof(*fwk) + fwk->num_services * - sizeof(fwk->svc_api_info[0]); - core->fwk_version = kmemdup(data->payload, bytes, GFP_ATOMIC); + core->fwk_version = kmemdup(data->payload, + struct_size(fwk, svc_api_info, + fwk->num_services), + GFP_ATOMIC); if (!core->fwk_version) return -ENOMEM; @@ -115,13 +115,13 @@ static int q6core_callback(struct apr_device *adev, struct apr_resp_pkt *data) } case AVCS_GET_VERSIONS_RSP: { struct avcs_cmdrsp_get_version *v; - int len; v = data->payload; - len = sizeof(*v) + v->num_services * sizeof(v->svc_api_info[0]); - - core->svc_version = kmemdup(data->payload, len, GFP_ATOMIC); + core->svc_version = kmemdup(data->payload, + struct_size(v, svc_api_info, + v->num_services), + GFP_ATOMIC); if (!core->svc_version) return -ENOMEM; From bd2956e40edf2160f5c1a623d6d6c6ab7f8cd831 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 27 May 2019 00:58:33 +0800 Subject: [PATCH 090/626] ALSA: hda: assign polling_mode after azx_bus_init We will move the polling_mode flag from struct azx to struct hdac_bus, and the flag should be assigned after bus init. Signed-off-by: Bard Liao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a4b0414dda3b..489fb53c9b06 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1701,10 +1701,6 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, else chip->bdl_pos_adj = bdl_pos_adj[dev]; - /* Workaround for a communication error on CFL (bko#199007) and CNL */ - if (IS_CFL(pci) || IS_CNL(pci)) - chip->polling_mode = 1; - err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); if (err < 0) { kfree(hda); @@ -1712,6 +1708,10 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, return err; } + /* Workaround for a communication error on CFL (bko#199007) and CNL */ + if (IS_CFL(pci) || IS_CNL(pci)) + chip->polling_mode = 1; + if (chip->driver_type == AZX_DRIVER_NVIDIA) { dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); chip->bus.needs_damn_long_delay = 1; From 8af42130b50c4d38f48fa82f3f7be4606d01f595 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 27 May 2019 00:58:34 +0800 Subject: [PATCH 091/626] ALSA: hda: move polling_mode flag to struct hdac_bus polling mode is a useful function in the get_response function. Move polling_mode flag from struct azx to struct hdac_bus so people can implement polling mode in their own get_response function without adding a polling_mode flag in their local chip structure. Signed-off-by: Bard Liao Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 3 +++ sound/pci/hda/hda_controller.c | 12 ++++++------ sound/pci/hda/hda_controller.h | 2 -- sound/pci/hda/hda_intel.c | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index e8346784cf3f..f49af557bdb0 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -358,6 +358,9 @@ struct hdac_bus { bool align_bdle_4k:1; /* BDLE align 4K boundary */ bool reverse_assign:1; /* assign devices in reverse order */ bool corbrp_self_clear:1; /* CORBRP clears itself after reset */ + bool polling_mode:1; + + int poll_count; int bdl_pos_adj; /* BDL position adjustment */ diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 532e081f8b8a..53feaeef1553 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -806,11 +806,11 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, for (loopcounter = 0;; loopcounter++) { spin_lock_irq(&bus->reg_lock); - if (chip->polling_mode || do_poll) + if (bus->polling_mode || do_poll) snd_hdac_bus_update_rirb(bus); if (!bus->rirb.cmds[addr]) { if (!do_poll) - chip->poll_count = 0; + bus->poll_count = 0; if (res) *res = bus->rirb.res[addr]; /* the last value */ spin_unlock_irq(&bus->reg_lock); @@ -830,21 +830,21 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, if (hbus->no_response_fallback) return -EIO; - if (!chip->polling_mode && chip->poll_count < 2) { + if (!bus->polling_mode && bus->poll_count < 2) { dev_dbg(chip->card->dev, "azx_get_response timeout, polling the codec once: last cmd=0x%08x\n", bus->last_cmd[addr]); do_poll = 1; - chip->poll_count++; + bus->poll_count++; goto again; } - if (!chip->polling_mode) { + if (!bus->polling_mode) { dev_warn(chip->card->dev, "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n", bus->last_cmd[addr]); - chip->polling_mode = 1; + bus->polling_mode = 1; goto again; } diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 7185ed574b41..8d886791cf0f 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -142,11 +142,9 @@ struct azx { /* flags */ int bdl_pos_adj; - int poll_count; unsigned int running:1; unsigned int fallback_to_single_cmd:1; unsigned int single_cmd:1; - unsigned int polling_mode:1; unsigned int msi:1; unsigned int probing:1; /* codec probing phase */ unsigned int snoop:1; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 489fb53c9b06..c0b466c96340 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1710,7 +1710,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, /* Workaround for a communication error on CFL (bko#199007) and CNL */ if (IS_CFL(pci) || IS_CNL(pci)) - chip->polling_mode = 1; + azx_bus(chip)->polling_mode = 1; if (chip->driver_type == AZX_DRIVER_NVIDIA) { dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); From 5e13cf6cd64c6a4c15a4426e6f1683093a495d9a Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 27 May 2019 00:58:35 +0800 Subject: [PATCH 092/626] ALSA: hda: add polling mode in snd_hdac_bus_get_response Polling mode is useful if a machine somehow missed an expected IRQ. Signed-off-by: Bard Liao Signed-off-by: Takashi Iwai --- sound/hda/hdac_controller.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index b2e9454f5816..a16ac31bda83 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -239,6 +239,8 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, timeout = jiffies + msecs_to_jiffies(1000); for (loopcounter = 0;; loopcounter++) { + if (bus->polling_mode) + snd_hdac_bus_update_rirb(bus); spin_lock_irq(&bus->reg_lock); if (!bus->rirb.cmds[addr]) { if (res) From 64ca9d9fcb3e3c86b1417e3d17a90b43dd660f81 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 27 May 2019 00:58:36 +0800 Subject: [PATCH 093/626] ASoC: SOF: Force polling mode on CFL and CNL There is a workaround in legacy HDA codec for too long time respone with CFL machine. We need the same workaround on SOF driver. The same issue is also seen on CNL machine. Signed-off-by: Bard Liao Signed-off-by: Takashi Iwai --- sound/soc/sof/intel/hda.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7e3980a2f7ba..ff973e8d054b 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -32,6 +32,9 @@ /* platform specific devices */ #include "shim.h" +#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) +#define IS_CNL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9dc8) + /* * Debug */ @@ -213,6 +216,11 @@ static int hda_init(struct snd_sof_dev *sdev) ext_ops = snd_soc_hdac_hda_get_ops(); #endif sof_hda_bus_init(bus, &pci->dev, ext_ops); + + /* Workaround for a communication error on CFL (bko#199007) and CNL */ + if (IS_CFL(pci) || IS_CNL(pci)) + bus->polling_mode = 1; + bus->use_posbuf = 1; bus->bdl_pos_adj = 0; From 516d3d1bedd34b2008f3530e4957ef97d449d5f7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2019 15:24:00 +0200 Subject: [PATCH 094/626] ALSA: line6: pod: Rewrite complex timer & work combo with a delayed work The POD driver had a complex staged startup procedure using both timer and work. This patch simplifies it via a single delayed work with the reduced stages. Now basically only two intermediate stages: - POD_STARTUP_VERSIONREQ: requesting the version information and the process_message callback triggers the next stage, - POD_STARTUP_SETUP: registering the actual card object. Signed-off-by: Takashi Iwai --- sound/usb/line6/pod.c | 94 ++++++++++++------------------------------- 1 file changed, 26 insertions(+), 68 deletions(-) diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c index ce45b6dab651..995e6ccc8122 100644 --- a/sound/usb/line6/pod.c +++ b/sound/usb/line6/pod.c @@ -39,11 +39,9 @@ Stages of POD startup procedure */ enum { - POD_STARTUP_INIT = 1, POD_STARTUP_VERSIONREQ, - POD_STARTUP_WORKQUEUE, POD_STARTUP_SETUP, - POD_STARTUP_LAST = POD_STARTUP_SETUP - 1 + POD_STARTUP_DONE, }; enum { @@ -63,12 +61,6 @@ struct usb_line6_pod { /* Instrument monitor level */ int monitor_level; - /* Timer for device initialization */ - struct timer_list startup_timer; - - /* Work handler for device initialization */ - struct work_struct startup_work; - /* Current progress in startup procedure */ int startup_progress; @@ -173,10 +165,6 @@ static const char pod_version_header[] = { 0xf2, 0x7e, 0x7f, 0x06, 0x02 }; -/* forward declarations: */ -static void pod_startup2(struct timer_list *t); -static void pod_startup3(struct usb_line6_pod *pod); - static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, int size) { @@ -196,7 +184,10 @@ static void line6_pod_process_message(struct usb_line6 *line6) pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15]; pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int) buf[10]; - pod_startup3(pod); + if (pod->startup_progress == POD_STARTUP_VERSIONREQ) { + pod->startup_progress = POD_STARTUP_SETUP; + schedule_delayed_work(&line6->startup_work, 0); + } return; } @@ -281,47 +272,27 @@ static ssize_t device_id_show(struct device *dev, context). After the last one has finished, the device is ready to use. */ -static void pod_startup1(struct usb_line6_pod *pod) +static void pod_startup(struct usb_line6 *line6) { - CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT); + struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; - /* delay startup procedure: */ - line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2); -} + switch (pod->startup_progress) { + case POD_STARTUP_VERSIONREQ: + /* request firmware version: */ + line6_version_request_async(line6); + break; + case POD_STARTUP_SETUP: + /* serial number: */ + line6_read_serial_number(&pod->line6, &pod->serial_number); -static void pod_startup2(struct timer_list *t) -{ - struct usb_line6_pod *pod = from_timer(pod, t, startup_timer); - struct usb_line6 *line6 = &pod->line6; - - CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ); - - /* request firmware version: */ - line6_version_request_async(line6); -} - -static void pod_startup3(struct usb_line6_pod *pod) -{ - CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE); - - /* schedule work for global work queue: */ - schedule_work(&pod->startup_work); -} - -static void pod_startup4(struct work_struct *work) -{ - struct usb_line6_pod *pod = - container_of(work, struct usb_line6_pod, startup_work); - struct usb_line6 *line6 = &pod->line6; - - CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP); - - /* serial number: */ - line6_read_serial_number(&pod->line6, &pod->serial_number); - - /* ALSA audio interface: */ - if (snd_card_register(line6->card)) - dev_err(line6->ifcdev, "Failed to register POD card.\n"); + /* ALSA audio interface: */ + if (snd_card_register(line6->card)) + dev_err(line6->ifcdev, "Failed to register POD card.\n"); + pod->startup_progress = POD_STARTUP_DONE; + break; + default: + break; + } } /* POD special files: */ @@ -390,17 +361,6 @@ static const struct snd_kcontrol_new pod_control_monitor = { .put = snd_pod_control_monitor_put }; -/* - POD device disconnected. -*/ -static void line6_pod_disconnect(struct usb_line6 *line6) -{ - struct usb_line6_pod *pod = (struct usb_line6_pod *)line6; - - del_timer_sync(&pod->startup_timer); - cancel_work_sync(&pod->startup_work); -} - /* Try to init POD device. */ @@ -411,10 +371,7 @@ static int pod_init(struct usb_line6 *line6, struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; line6->process_message = line6_pod_process_message; - line6->disconnect = line6_pod_disconnect; - - timer_setup(&pod->startup_timer, NULL, 0); - INIT_WORK(&pod->startup_work, pod_startup4); + line6->startup = pod_startup; /* create sysfs entries: */ err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group); @@ -447,7 +404,8 @@ static int pod_init(struct usb_line6 *line6, pod->monitor_level = POD_SYSTEM_INVALID; /* initiate startup procedure: */ - pod_startup1(pod); + schedule_delayed_work(&line6->startup_work, + msecs_to_jiffies(POD_STARTUP_DELAY)); } return 0; From a91c1da77c99f1552c58a4451fc8972336627a53 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2019 15:31:00 +0200 Subject: [PATCH 095/626] ALSA: line6: podhd: Rewrite complex timer & work combo with a delayed work POD HD driver had a complex staged startup sequence with both timer and work. This patch simplifies it to a single delayed work with a single stage. Signed-off-by: Takashi Iwai --- sound/usb/line6/podhd.c | 74 +++++------------------------------------ 1 file changed, 8 insertions(+), 66 deletions(-) diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 5f3c87264e66..722fc5db09c5 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -22,16 +22,6 @@ #define PODHD_STARTUP_DELAY 500 -/* - * Stages of POD startup procedure - */ -enum { - PODHD_STARTUP_INIT = 1, - PODHD_STARTUP_SCHEDULE_WORKQUEUE, - PODHD_STARTUP_SETUP, - PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1 -}; - enum { LINE6_PODHD300, LINE6_PODHD400, @@ -47,15 +37,6 @@ struct usb_line6_podhd { /* Generic Line 6 USB data */ struct usb_line6 line6; - /* Timer for device initialization */ - struct timer_list startup_timer; - - /* Work handler for device initialization */ - struct work_struct startup_work; - - /* Current progress in startup procedure */ - int startup_progress; - /* Serial number of device */ u32 serial_number; @@ -158,10 +139,6 @@ static struct line6_pcm_properties podx3_pcm_properties = { }; static struct usb_driver podhd_driver; -static void podhd_startup_start_workqueue(struct timer_list *t); -static void podhd_startup_workqueue(struct work_struct *work); -static int podhd_startup_finalize(struct usb_line6_podhd *pod); - static ssize_t serial_number_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -202,26 +179,6 @@ static const struct attribute_group podhd_dev_attr_group = { * audio nor bulk interfaces to work. */ -static void podhd_startup(struct usb_line6_podhd *pod) -{ - CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT); - - /* delay startup procedure: */ - line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY, - podhd_startup_start_workqueue); -} - -static void podhd_startup_start_workqueue(struct timer_list *t) -{ - struct usb_line6_podhd *pod = from_timer(pod, t, startup_timer); - - CHECK_STARTUP_PROGRESS(pod->startup_progress, - PODHD_STARTUP_SCHEDULE_WORKQUEUE); - - /* schedule work for global work queue: */ - schedule_work(&pod->startup_work); -} - static int podhd_dev_start(struct usb_line6_podhd *pod) { int ret; @@ -272,25 +229,14 @@ exit: return ret; } -static void podhd_startup_workqueue(struct work_struct *work) +static void podhd_startup(struct usb_line6 *line6) { - struct usb_line6_podhd *pod = - container_of(work, struct usb_line6_podhd, startup_work); - - CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP); + struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; podhd_dev_start(pod); line6_read_serial_number(&pod->line6, &pod->serial_number); - - podhd_startup_finalize(pod); -} - -static int podhd_startup_finalize(struct usb_line6_podhd *pod) -{ - struct usb_line6 *line6 = &pod->line6; - - /* ALSA audio interface: */ - return snd_card_register(line6->card); + if (snd_card_register(line6->card)) + dev_err(line6->ifcdev, "Failed to register POD HD card.\n"); } static void podhd_disconnect(struct usb_line6 *line6) @@ -300,9 +246,6 @@ static void podhd_disconnect(struct usb_line6 *line6) if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { struct usb_interface *intf; - del_timer_sync(&pod->startup_timer); - cancel_work_sync(&pod->startup_work); - intf = usb_ifnum_to_if(line6->usbdev, pod->line6.properties->ctrl_if); if (intf) @@ -321,9 +264,7 @@ static int podhd_init(struct usb_line6 *line6, struct usb_interface *intf; line6->disconnect = podhd_disconnect; - - timer_setup(&pod->startup_timer, NULL, 0); - INIT_WORK(&pod->startup_work, podhd_startup_workqueue); + line6->startup = podhd_startup; if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { /* claim the data interface */ @@ -362,11 +303,12 @@ static int podhd_init(struct usb_line6 *line6, if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) { /* register USB audio system directly */ - return podhd_startup_finalize(pod); + return snd_card_register(line6->card); } /* init device and delay registering */ - podhd_startup(pod); + schedule_delayed_work(&line6->startup_work, + msecs_to_jiffies(PODHD_STARTUP_DELAY)); return 0; } From 6ea53391c04ebc84ff62e2df20f75d65f727f4e8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2019 15:55:36 +0200 Subject: [PATCH 096/626] ALSA: line6: variax: Rewrite complex timer & work combo with a delayed work Variax driver had a very complex and staged startup sequence using multiple timers and a work. This patch simplifies the procedure to a single delayed work. Now the startup stage consists of: - VARIAX_STARTUP_VERSIONREQ: requesting the version and the message handler raises up to the next stage upon receiving the reply. The request is repeated until a reply arrives. - VARIAX_STARTUP_ACTIVATE: does activation, and queue for the next stage. - VARIAX_STARTUP_SETUP: registers the card. Signed-off-by: Takashi Iwai --- sound/usb/line6/variax.c | 128 +++++++++++---------------------------- 1 file changed, 35 insertions(+), 93 deletions(-) diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c index e8c852b2ce35..fb114156b7ca 100644 --- a/sound/usb/line6/variax.c +++ b/sound/usb/line6/variax.c @@ -26,13 +26,9 @@ Stages of Variax startup procedure */ enum { - VARIAX_STARTUP_INIT = 1, VARIAX_STARTUP_VERSIONREQ, - VARIAX_STARTUP_WAIT, VARIAX_STARTUP_ACTIVATE, - VARIAX_STARTUP_WORKQUEUE, VARIAX_STARTUP_SETUP, - VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1 }; enum { @@ -47,13 +43,6 @@ struct usb_line6_variax { /* Buffer for activation code */ unsigned char *buffer_activate; - /* Handler for device initialization */ - struct work_struct startup_work; - - /* Timers for device initialization */ - struct timer_list startup_timer1; - struct timer_list startup_timer2; - /* Current progress in startup procedure */ int startup_progress; }; @@ -81,11 +70,6 @@ static const char variax_activate[] = { 0xf7 }; -/* forward declarations: */ -static void variax_startup2(struct timer_list *t); -static void variax_startup4(struct timer_list *t); -static void variax_startup5(struct timer_list *t); - static void variax_activate_async(struct usb_line6_variax *variax, int a) { variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a; @@ -100,74 +84,30 @@ static void variax_activate_async(struct usb_line6_variax *variax, int a) context). After the last one has finished, the device is ready to use. */ -static void variax_startup1(struct usb_line6_variax *variax) +static void variax_startup(struct usb_line6 *line6) { - CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT); + struct usb_line6_variax *variax = (struct usb_line6_variax *)line6; - /* delay startup procedure: */ - line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, - variax_startup2); -} - -static void variax_startup2(struct timer_list *t) -{ - struct usb_line6_variax *variax = from_timer(variax, t, startup_timer1); - struct usb_line6 *line6 = &variax->line6; - - /* schedule another startup procedure until startup is complete: */ - if (variax->startup_progress >= VARIAX_STARTUP_LAST) - return; - - variax->startup_progress = VARIAX_STARTUP_VERSIONREQ; - line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, - variax_startup2); - - /* request firmware version: */ - line6_version_request_async(line6); -} - -static void variax_startup3(struct usb_line6_variax *variax) -{ - CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT); - - /* delay startup procedure: */ - line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3, - variax_startup4); -} - -static void variax_startup4(struct timer_list *t) -{ - struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2); - - CHECK_STARTUP_PROGRESS(variax->startup_progress, - VARIAX_STARTUP_ACTIVATE); - - /* activate device: */ - variax_activate_async(variax, 1); - line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4, - variax_startup5); -} - -static void variax_startup5(struct timer_list *t) -{ - struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2); - - CHECK_STARTUP_PROGRESS(variax->startup_progress, - VARIAX_STARTUP_WORKQUEUE); - - /* schedule work for global work queue: */ - schedule_work(&variax->startup_work); -} - -static void variax_startup6(struct work_struct *work) -{ - struct usb_line6_variax *variax = - container_of(work, struct usb_line6_variax, startup_work); - - CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP); - - /* ALSA audio interface: */ - snd_card_register(variax->line6.card); + switch (variax->startup_progress) { + case VARIAX_STARTUP_VERSIONREQ: + /* repeat request until getting the response */ + schedule_delayed_work(&line6->startup_work, + msecs_to_jiffies(VARIAX_STARTUP_DELAY1)); + /* request firmware version: */ + line6_version_request_async(line6); + break; + case VARIAX_STARTUP_ACTIVATE: + /* activate device: */ + variax_activate_async(variax, 1); + variax->startup_progress = VARIAX_STARTUP_SETUP; + schedule_delayed_work(&line6->startup_work, + msecs_to_jiffies(VARIAX_STARTUP_DELAY4)); + break; + case VARIAX_STARTUP_SETUP: + /* ALSA audio interface: */ + snd_card_register(variax->line6.card); + break; + } } /* @@ -186,11 +126,19 @@ static void line6_variax_process_message(struct usb_line6 *line6) case LINE6_SYSEX_BEGIN: if (memcmp(buf + 1, variax_init_version + 1, sizeof(variax_init_version) - 1) == 0) { - variax_startup3(variax); + if (variax->startup_progress >= VARIAX_STARTUP_ACTIVATE) + break; + variax->startup_progress = VARIAX_STARTUP_ACTIVATE; + cancel_delayed_work(&line6->startup_work); + schedule_delayed_work(&line6->startup_work, + msecs_to_jiffies(VARIAX_STARTUP_DELAY3)); } else if (memcmp(buf + 1, variax_init_done + 1, sizeof(variax_init_done) - 1) == 0) { /* notify of complete initialization: */ - variax_startup4(&variax->startup_timer2); + if (variax->startup_progress >= VARIAX_STARTUP_SETUP) + break; + cancel_delayed_work(&line6->startup_work); + schedule_delayed_work(&line6->startup_work, 0); } break; } @@ -203,10 +151,6 @@ static void line6_variax_disconnect(struct usb_line6 *line6) { struct usb_line6_variax *variax = (struct usb_line6_variax *)line6; - del_timer(&variax->startup_timer1); - del_timer(&variax->startup_timer2); - cancel_work_sync(&variax->startup_work); - kfree(variax->buffer_activate); } @@ -221,10 +165,7 @@ static int variax_init(struct usb_line6 *line6, line6->process_message = line6_variax_process_message; line6->disconnect = line6_variax_disconnect; - - timer_setup(&variax->startup_timer1, NULL, 0); - timer_setup(&variax->startup_timer2, NULL, 0); - INIT_WORK(&variax->startup_work, variax_startup6); + line6->startup = variax_startup; /* initialize USB buffers: */ variax->buffer_activate = kmemdup(variax_activate, @@ -239,7 +180,8 @@ static int variax_init(struct usb_line6 *line6, return err; /* initiate startup procedure: */ - variax_startup1(variax); + schedule_delayed_work(&line6->startup_work, + msecs_to_jiffies(VARIAX_STARTUP_DELAY1)); return 0; } From be8fd484e9c23e49ffe1d163c8d32c8c7b745941 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2019 15:56:29 +0200 Subject: [PATCH 097/626] ALSA: line6: Drop superfluous timer helper function Now all timer usages in line6 drivers are gone, we can get rid of some helper macro and function that became superfluous. Signed-off-by: Takashi Iwai --- sound/usb/line6/driver.c | 11 ----------- sound/usb/line6/driver.h | 9 --------- 2 files changed, 20 deletions(-) diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 2b57854335b3..79e96b269411 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -195,17 +195,6 @@ static int line6_send_raw_message_async_part(struct message *msg, return retval; } -/* - Setup and start timer. -*/ -void line6_start_timer(struct timer_list *timer, unsigned long msecs, - void (*function)(struct timer_list *t)) -{ - timer->function = function; - mod_timer(timer, jiffies + msecs_to_jiffies(msecs)); -} -EXPORT_SYMBOL_GPL(line6_start_timer); - /* Asynchronously send raw message. */ diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 650d909c9c4f..4eb66cdf1ece 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -68,13 +68,6 @@ #define LINE6_CHANNEL_MASK 0x0f -#define CHECK_STARTUP_PROGRESS(x, n) \ -do { \ - if ((x) >= (n)) \ - return; \ - x = (n); \ -} while (0) - extern const unsigned char line6_midi_id[3]; static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3; @@ -201,8 +194,6 @@ extern int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer, int size); extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); -extern void line6_start_timer(struct timer_list *timer, unsigned long msecs, - void (*function)(struct timer_list *t)); extern int line6_version_request_async(struct usb_line6 *line6); extern int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, unsigned datalen); From f23a09eea1e7947611d985d8cd13d55428ff0af8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 28 May 2019 09:05:31 +0200 Subject: [PATCH 098/626] ALSA: line6: Use container_of() ... instead of unconditional cast. Signed-off-by: Takashi Iwai --- sound/usb/line6/pod.c | 12 +++++++----- sound/usb/line6/podhd.c | 8 +++++--- sound/usb/line6/toneport.c | 14 +++++++------- sound/usb/line6/variax.c | 10 ++++++---- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c index 995e6ccc8122..9ea720b4b2ab 100644 --- a/sound/usb/line6/pod.c +++ b/sound/usb/line6/pod.c @@ -74,6 +74,8 @@ struct usb_line6_pod { int device_id; }; +#define line6_to_pod(x) container_of(x, struct usb_line6_pod, line6) + #define POD_SYSEX_CODE 3 /* *INDENT-OFF* */ @@ -177,7 +179,7 @@ static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, */ static void line6_pod_process_message(struct usb_line6 *line6) { - struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; + struct usb_line6_pod *pod = line6_to_pod(line6); const unsigned char *buf = pod->line6.buffer_message; if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) { @@ -274,7 +276,7 @@ static ssize_t device_id_show(struct device *dev, static void pod_startup(struct usb_line6 *line6) { - struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; + struct usb_line6_pod *pod = line6_to_pod(line6); switch (pod->startup_progress) { case POD_STARTUP_VERSIONREQ: @@ -328,7 +330,7 @@ static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); - struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; + struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6); ucontrol->value.integer.value[0] = pod->monitor_level; return 0; @@ -339,7 +341,7 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); - struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; + struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6); if (ucontrol->value.integer.value[0] == pod->monitor_level) return 0; @@ -368,7 +370,7 @@ static int pod_init(struct usb_line6 *line6, const struct usb_device_id *id) { int err; - struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; + struct usb_line6_pod *pod = line6_to_pod(line6); line6->process_message = line6_pod_process_message; line6->startup = pod_startup; diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 722fc5db09c5..395ae1692f45 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -44,6 +44,8 @@ struct usb_line6_podhd { int firmware_version; }; +#define line6_to_podhd(x) container_of(x, struct usb_line6_podhd, line6) + static struct snd_ratden podhd_ratden = { .num_min = 48000, .num_max = 48000, @@ -231,7 +233,7 @@ exit: static void podhd_startup(struct usb_line6 *line6) { - struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; + struct usb_line6_podhd *pod = line6_to_podhd(line6); podhd_dev_start(pod); line6_read_serial_number(&pod->line6, &pod->serial_number); @@ -241,7 +243,7 @@ static void podhd_startup(struct usb_line6 *line6) static void podhd_disconnect(struct usb_line6 *line6) { - struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; + struct usb_line6_podhd *pod = line6_to_podhd(line6); if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { struct usb_interface *intf; @@ -260,7 +262,7 @@ static int podhd_init(struct usb_line6 *line6, const struct usb_device_id *id) { int err; - struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6; + struct usb_line6_podhd *pod = line6_to_podhd(line6); struct usb_interface *intf; line6->disconnect = podhd_disconnect; diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index 55865f7e437d..94a9764110d3 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c @@ -61,6 +61,8 @@ struct usb_line6_toneport { struct toneport_led leds[2]; }; +#define line6_to_toneport(x) container_of(x, struct usb_line6_toneport, line6) + static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); #define TONEPORT_PCM_DELAY 1 @@ -211,8 +213,8 @@ static int snd_toneport_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); - struct usb_line6_toneport *toneport = - (struct usb_line6_toneport *)line6pcm->line6; + struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6); + ucontrol->value.enumerated.item[0] = toneport->source; return 0; } @@ -222,8 +224,7 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); - struct usb_line6_toneport *toneport = - (struct usb_line6_toneport *)line6pcm->line6; + struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6); unsigned int source; source = ucontrol->value.enumerated.item[0]; @@ -397,8 +398,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport) */ static void line6_toneport_disconnect(struct usb_line6 *line6) { - struct usb_line6_toneport *toneport = - (struct usb_line6_toneport *)line6; + struct usb_line6_toneport *toneport = line6_to_toneport(line6); if (toneport_has_led(toneport)) toneport_remove_leds(toneport); @@ -412,7 +412,7 @@ static int toneport_init(struct usb_line6 *line6, const struct usb_device_id *id) { int err; - struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6; + struct usb_line6_toneport *toneport = line6_to_toneport(line6); toneport->type = id->driver_info; diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c index fb114156b7ca..0d0de907d497 100644 --- a/sound/usb/line6/variax.c +++ b/sound/usb/line6/variax.c @@ -47,6 +47,8 @@ struct usb_line6_variax { int startup_progress; }; +#define line6_to_variax(x) container_of(x, struct usb_line6_variax, line6) + #define VARIAX_OFFSET_ACTIVATE 7 /* @@ -86,7 +88,7 @@ static void variax_activate_async(struct usb_line6_variax *variax, int a) static void variax_startup(struct usb_line6 *line6) { - struct usb_line6_variax *variax = (struct usb_line6_variax *)line6; + struct usb_line6_variax *variax = line6_to_variax(line6); switch (variax->startup_progress) { case VARIAX_STARTUP_VERSIONREQ: @@ -115,7 +117,7 @@ static void variax_startup(struct usb_line6 *line6) */ static void line6_variax_process_message(struct usb_line6 *line6) { - struct usb_line6_variax *variax = (struct usb_line6_variax *) line6; + struct usb_line6_variax *variax = line6_to_variax(line6); const unsigned char *buf = variax->line6.buffer_message; switch (buf[0]) { @@ -149,7 +151,7 @@ static void line6_variax_process_message(struct usb_line6 *line6) */ static void line6_variax_disconnect(struct usb_line6 *line6) { - struct usb_line6_variax *variax = (struct usb_line6_variax *)line6; + struct usb_line6_variax *variax = line6_to_variax(line6); kfree(variax->buffer_activate); } @@ -160,7 +162,7 @@ static void line6_variax_disconnect(struct usb_line6 *line6) static int variax_init(struct usb_line6 *line6, const struct usb_device_id *id) { - struct usb_line6_variax *variax = (struct usb_line6_variax *) line6; + struct usb_line6_variax *variax = line6_to_variax(line6); int err; line6->process_message = line6_variax_process_message; From 9b33d2e526c53b0339ddba8b875bb8b8b3a11207 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 24 May 2019 22:44:19 +0100 Subject: [PATCH 099/626] ASoC: cx2072x: remove redundant assignment to pulse_len Variable pulse_len is being initialized to 1 however this value is never read and pulse_len is being re-assigned later in a switch statement. Clean up the code by removing the redundant initialization. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Reviewed-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index 23d2b25fe04c..c11a585bbf70 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -679,7 +679,7 @@ static int cx2072x_config_i2spcm(struct cx2072x_priv *cx2072x) int is_right_j = 0; int is_frame_inv = 0; int is_bclk_inv = 0; - int pulse_len = 1; + int pulse_len; int frame_len = cx2072x->frame_size; int sample_size = cx2072x->sample_size; int i2s_right_slot; From 41f4fadb34af8cdcd7c1e7b4118b8db14d06849e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 24 May 2019 11:10:51 -0500 Subject: [PATCH 100/626] ASoC: SOF: topology: Use struct_size() helper Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes, in particular in the context in which this code is being used. So, replace the following form: sizeof(struct sof_ipc_ctrl_data) + sizeof(struct sof_ipc_ctrl_value_chan) * le32_to_cpu(mc->num_channels) with: struct_size(scontrol->control_data, chanv, le32_to_cpu(mc->num_channels)) and so on... This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index c88afa872a58..745cb875863c 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -442,9 +442,8 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, return -EINVAL; /* init the volume get/put data */ - scontrol->size = sizeof(struct sof_ipc_ctrl_data) + - sizeof(struct sof_ipc_ctrl_value_chan) * - le32_to_cpu(mc->num_channels); + scontrol->size = struct_size(scontrol->control_data, chanv, + le32_to_cpu(mc->num_channels)); scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); if (!scontrol->control_data) return -ENOMEM; @@ -501,9 +500,8 @@ static int sof_control_load_enum(struct snd_soc_component *scomp, return -EINVAL; /* init the enum get/put data */ - scontrol->size = sizeof(struct sof_ipc_ctrl_data) + - sizeof(struct sof_ipc_ctrl_value_chan) * - le32_to_cpu(ec->num_channels); + scontrol->size = struct_size(scontrol->control_data, chanv, + le32_to_cpu(ec->num_channels)); scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); if (!scontrol->control_data) return -ENOMEM; From b2045303147254d01b1db90a83e5df3832c4264b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 27 May 2019 22:06:21 +0200 Subject: [PATCH 101/626] dt-bindings: sound: sun4i-spdif: Add Allwinner H6 compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allwinner H6 has a SPDIF controller with an increase of the fifo size and a sligher difference in memory mapping compare to H3/A64. This make it not compatible with the previous generation. Introduce a specific bindings for H6 SoC. Signed-off-by: Clément Péron Reviewed-by: Rob Herring Acked-by: Maxime Ripard Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml index a49ef2294a74..e0284d8c3b63 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml @@ -21,6 +21,7 @@ properties: - const: allwinner,sun4i-a10-spdif - const: allwinner,sun6i-a31-spdif - const: allwinner,sun8i-h3-spdif + - const: allwinner,sun50i-h6-spdif - items: - const: allwinner,sun8i-a83t-spdif - const: allwinner,sun8i-h3-spdif From 99afc8df8b6f2d039b1ab20d879e4721068a6c34 Mon Sep 17 00:00:00 2001 From: Maxime Jourdan Date: Mon, 27 May 2019 18:38:09 +0200 Subject: [PATCH 102/626] ASoC: max98357a: Show KConfig entry The SEI510 board features a standalone MAX98357A codec. Add a tristate prompt to allow selecting the codec. Signed-off-by: Maxime Jourdan Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 472bde124ebe..0835d4b0d8c3 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -714,7 +714,8 @@ config SND_SOC_MAX98095 tristate config SND_SOC_MAX98357A - tristate + tristate "Maxim MAX98357A CODEC" + depends on GPIOLIB config SND_SOC_MAX98371 tristate From b11c5b5e573968d69aa9fec7507de7aa8fbf76e6 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 May 2019 10:58:00 -0500 Subject: [PATCH 103/626] ASoC: SOF: Use struct_size() in kmemdup() Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes, in particular in the context in which this code is being used. So, replace code of the following form: sizeof(*w) + sizeof(struct sof_ipc_window_elem) * w->num_windows with: struct_size(w, window, w->num_windows) Notice that variable size is unnecessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 628fae552442..16b016b76fd8 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -19,15 +19,13 @@ static int get_ext_windows(struct snd_sof_dev *sdev, { struct sof_ipc_window *w = container_of(ext_hdr, struct sof_ipc_window, ext_hdr); - size_t size; if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) return -EINVAL; - size = sizeof(*w) + sizeof(struct sof_ipc_window_elem) * w->num_windows; - /* keep a local copy of the data */ - sdev->info_window = kmemdup(w, size, GFP_KERNEL); + sdev->info_window = kmemdup(w, struct_size(w, window, w->num_windows), + GFP_KERNEL); if (!sdev->info_window) return -ENOMEM; From f627b0524ccf993b646bd56f9bdacc973c8c39cc Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 24 May 2019 14:23:05 -0500 Subject: [PATCH 104/626] ASoC: SOF: trace: remove code duplication in sof_wait_trace_avail() Move duplicated code in sof_wait_trace_avail() to a helper function. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/trace.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index d588e4b70fad..a2d89d295f0f 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -13,10 +13,9 @@ #include "sof-priv.h" #include "ops.h" -static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev, - loff_t pos, size_t buffer_size) +static size_t sof_trace_avail(struct snd_sof_dev *sdev, + loff_t pos, size_t buffer_size) { - wait_queue_entry_t wait; loff_t host_offset = READ_ONCE(sdev->host_offset); /* @@ -31,6 +30,19 @@ static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev, if (host_offset > pos) return host_offset - pos; + return 0; +} + +static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev, + loff_t pos, size_t buffer_size) +{ + wait_queue_entry_t wait; + size_t ret = sof_trace_avail(sdev, pos, buffer_size); + + /* data immediately available */ + if (ret) + return ret; + /* wait for available trace data from FW */ init_waitqueue_entry(&wait, current); set_current_state(TASK_INTERRUPTIBLE); @@ -42,12 +54,7 @@ static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev, } remove_wait_queue(&sdev->trace_sleep, &wait); - /* return bytes available for copy */ - host_offset = READ_ONCE(sdev->host_offset); - if (host_offset < pos) - return buffer_size - pos; - - return host_offset - pos; + return sof_trace_avail(sdev, pos, buffer_size); } static ssize_t sof_dfsentry_trace_read(struct file *file, char __user *buffer, From ec9025e5d3c5b5f2027fa74be6afdaad9908b546 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 24 May 2019 14:23:06 -0500 Subject: [PATCH 105/626] ASoC: SOF: force end-of-file for debugfs trace at suspend Current trace implementation gets out of sync when sof device is put to suspend. The debugfs file handle is kept open, but firmware will reset its state. After resume, debugfs client's read offset will not be synchronized to firmware and this may result in traces read in incorrect order and/or stale data being read after resume. Add logic to signal end-of-file to read() when firmware tracing has ended, and all trace data has been read. This allows debugfs client to capture all trace data, and reopen the trace file to ensure proper synchronization with firmware after reopening the node. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/sof-priv.h | 2 ++ sound/soc/sof/trace.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 1e85d6f9c5c3..01a6219c326b 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -417,6 +417,8 @@ struct snd_sof_dev { u32 host_offset; u32 dtrace_is_enabled; u32 dtrace_error; + u32 dtrace_draining; + u32 msi_enabled; void *private; /* core does not touch this */ diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index a2d89d295f0f..b02520f8e595 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -43,6 +43,15 @@ static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev, if (ret) return ret; + if (!sdev->dtrace_is_enabled && sdev->dtrace_draining) { + /* + * tracing has ended and all traces have been + * read by client, return EOF + */ + sdev->dtrace_draining = false; + return 0; + } + /* wait for available trace data from FW */ init_waitqueue_entry(&wait, current); set_current_state(TASK_INTERRUPTIBLE); @@ -104,10 +113,23 @@ static ssize_t sof_dfsentry_trace_read(struct file *file, char __user *buffer, return count; } +static int sof_dfsentry_trace_release(struct inode *inode, struct file *file) +{ + struct snd_sof_dfsentry *dfse = inode->i_private; + struct snd_sof_dev *sdev = dfse->sdev; + + /* avoid duplicate traces at next open */ + if (!sdev->dtrace_is_enabled) + sdev->host_offset = 0; + + return 0; +} + static const struct file_operations sof_dfs_trace_fops = { .open = simple_open, .read = sof_dfsentry_trace_read, .llseek = default_llseek, + .release = sof_dfsentry_trace_release, }; static int trace_debugfs_create(struct snd_sof_dev *sdev) @@ -155,6 +177,7 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev) params.stream_tag = 0; sdev->host_offset = 0; + sdev->dtrace_draining = false; ret = snd_sof_dma_trace_init(sdev, ¶ms.stream_tag); if (ret < 0) { @@ -291,6 +314,8 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev) "error: fail in snd_sof_dma_trace_release %d\n", ret); sdev->dtrace_is_enabled = false; + sdev->dtrace_draining = true; + wake_up(&sdev->trace_sleep); } EXPORT_SYMBOL(snd_sof_release_trace); From 0a0ca8e94ca36d2153c2fbea69a31f792bfc5831 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 24 May 2019 14:57:58 +0200 Subject: [PATCH 106/626] dt-bindings: sound: Convert Allwinner I2S binding to YAML The Allwinner SoCs feature an I2S controller across multiple SoC generations. However, earlier generations were a bit simpler than the subsequent ones, and for example would always have RX and TX capabilities, and no reset lines. Signed-off-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Mark Brown --- .../sound/allwinner,sun4i-a10-i2s.yaml | 100 ++++++++++++++++++ .../devicetree/bindings/sound/sun4i-i2s.txt | 45 -------- 2 files changed, 100 insertions(+), 45 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml delete mode 100644 Documentation/devicetree/bindings/sound/sun4i-i2s.txt diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml new file mode 100644 index 000000000000..85b2d6d84055 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml @@ -0,0 +1,100 @@ +# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/allwinner,sun4i-a10-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 I2S Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#sound-dai-cells": + const: 0 + + compatible: + oneOf: + - const: allwinner,sun4i-a10-i2s + - const: allwinner,sun6i-a31-i2s + - const: allwinner,sun8i-a83t-i2s + - const: allwinner,sun8i-h3-i2s + - const: allwinner,sun50i-a64-codec-i2s + - items: + - const: allwinner,sun50i-a64-i2s + - const: allwinner,sun8i-h3-i2s + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + + clock-names: + items: + - const: apb + - const: mod + + dmas: + items: + - description: RX DMA Channel + - description: TX DMA Channel + + dma-names: + items: + - const: rx + - const: tx + + # Even though it only applies to subschemas under the conditionals, + # not listing them here will trigger a warning because of the + # additionalsProperties set to false. + resets: + maxItems: 1 + +allOf: + - if: + properties: + compatible: + contains: + enum: + - allwinner,sun6i-a31-i2s + - allwinner,sun8i-a83t-i2s + - allwinner,sun8i-h3-i2s + - allwinner,sun50i-a64-codec-i2s + + then: + required: + - resets + +required: + - "#sound-dai-cells" + - compatible + - reg + - interrupts + - clocks + - clock-names + - dmas + - dma-names + +additionalProperties: false + +examples: + - | + i2s0: i2s@1c22400 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun4i-a10-i2s"; + reg = <0x01c22400 0x400>; + interrupts = <0 16 4>; + clocks = <&apb0_gates 3>, <&i2s0_clk>; + clock-names = "apb", "mod"; + dmas = <&dma 0 3>, <&dma 0 3>; + dma-names = "rx", "tx"; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt deleted file mode 100644 index 61e71c1729e0..000000000000 --- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt +++ /dev/null @@ -1,45 +0,0 @@ -* Allwinner A10 I2S controller - -The I2S bus (Inter-IC sound bus) is a serial link for digital -audio data transfer between devices in the system. - -Required properties: - -- compatible: should be one of the following: - - "allwinner,sun4i-a10-i2s" - - "allwinner,sun6i-a31-i2s" - - "allwinner,sun8i-a83t-i2s" - - "allwinner,sun8i-h3-i2s" - - "allwinner,sun50i-a64-codec-i2s" -- reg: physical base address of the controller and length of memory mapped - region. -- interrupts: should contain the I2S interrupt. -- dmas: DMA specifiers for tx and rx dma. See the DMA client binding, - Documentation/devicetree/bindings/dma/dma.txt -- dma-names: should include "tx" and "rx". -- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. -- clock-names: should contain the following: - - "apb" : clock for the I2S bus interface - - "mod" : module clock for the I2S controller -- #sound-dai-cells : Must be equal to 0 - -Required properties for the following compatibles: - - "allwinner,sun6i-a31-i2s" - - "allwinner,sun8i-a83t-i2s" - - "allwinner,sun8i-h3-i2s" - - "allwinner,sun50i-a64-codec-i2s" -- resets: phandle to the reset line for this codec - -Example: - -i2s0: i2s@1c22400 { - #sound-dai-cells = <0>; - compatible = "allwinner,sun4i-a10-i2s"; - reg = <0x01c22400 0x400>; - interrupts = ; - clocks = <&apb0_gates 3>, <&i2s0_clk>; - clock-names = "apb", "mod"; - dmas = <&dma SUN4I_DMA_NORMAL 3>, - <&dma SUN4I_DMA_NORMAL 3>; - dma-names = "rx", "tx"; -}; From eb5b12843b067d685a8d7a191b928b07934b2d02 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 24 May 2019 14:57:59 +0200 Subject: [PATCH 107/626] dt-bindings: sound: sun4i-i2s: Document that the RX channel can be missing The A83t and compatibles controllers don't have any reception capabilities on some instances of the controllers, even though it was never documented as such in the binding before. Therefore, on those controllers, we don't have the option to set an RX DMA channel. This was already done in the DTSI, but the binding itself was never updated. Let's add a special case in the schemas. Signed-off-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Mark Brown --- .../sound/allwinner,sun4i-a10-i2s.yaml | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml index 85b2d6d84055..eb3992138eec 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml @@ -41,19 +41,11 @@ properties: - const: apb - const: mod - dmas: - items: - - description: RX DMA Channel - - description: TX DMA Channel - - dma-names: - items: - - const: rx - - const: tx - # Even though it only applies to subschemas under the conditionals, # not listing them here will trigger a warning because of the # additionalsProperties set to false. + dmas: true + dma-names: true resets: maxItems: 1 @@ -72,6 +64,46 @@ allOf: required: - resets + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-a83t-i2s + + then: + properties: + dmas: + minItems: 1 + maxItems: 2 + items: + - description: RX DMA Channel + - description: TX DMA Channel + description: + Some controllers cannot receive but can only transmit + data. In such a case, the RX DMA channel is to be omitted. + + dma-names: + oneOf: + - items: + - const: rx + - const: tx + - const: tx + description: + Some controllers cannot receive but can only transmit + data. In such a case, the RX name is to be omitted. + + else: + properties: + dmas: + items: + - description: RX DMA Channel + - description: TX DMA Channel + + dma-names: + items: + - const: rx + - const: tx + required: - "#sound-dai-cells" - compatible From be0461048b60066eaba9046178fb96e78579af21 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 24 May 2019 23:25:51 +0100 Subject: [PATCH 108/626] ASoC: cx2072x: fix integer overflow on unsigned int multiply In the case where frac_div larger than 96 the result of an unsigned multiplication overflows an unsigned int. For example, this can happen when the sample_rate is 192000 and pll_input is 122. Fix this by casing the first term of the mutiply to a u64. Also remove the extraneous parentheses around the expression. Addresses-Coverity: ("Unintentional integer overflow") Fixes: a497a4363706 ("ASoC: Add support for Conexant CX2072X CODEC") Signed-off-by: Colin Ian King Reviewed-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index c11a585bbf70..ed762546eaee 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -627,7 +627,7 @@ static int cx2072x_config_pll(struct cx2072x_priv *cx2072x) if (frac_div) { frac_div *= 1000; frac_div /= pll_input; - frac_num = ((4000 + frac_div) * ((1 << 20) - 4)); + frac_num = (u64)(4000 + frac_div) * ((1 << 20) - 4); do_div(frac_num, 7); frac = ((u32)frac_num + 499) / 1000; } From 9aa37874d1930da139a08f4db1eff5d305f2ddc8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 25 May 2019 21:32:44 +0100 Subject: [PATCH 109/626] ASoC: cx2072x: fix spelling mistake "configued" -> "configured" There is a spelling mistake in a dev_err error message. Fit it. Signed-off-by: Colin Ian King Reviewed-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index ed762546eaee..8b0830854bb3 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -933,7 +933,7 @@ static int cx2072x_hw_params(struct snd_pcm_substream *substream, return frame_size; if (cx2072x->mclk_rate == 0) { - dev_err(dev, "Master clock rate is not configued\n"); + dev_err(dev, "Master clock rate is not configured\n"); return -EINVAL; } From ae9cccc30f6c088dd6ead63e990407e37cd9437b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 27 May 2019 22:06:22 +0200 Subject: [PATCH 110/626] ASoC: sun4i-spdif: Move quirks to the top MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The quirks are actually defines in the middle of the file with short explanation. Move this at the top and add a section to have coherency with sun4i-i2s. Signed-off-by: Clément Péron Acked-by: Maxime Ripard Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-spdif.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index b4af4aabead1..b6c66a62e915 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -161,6 +161,17 @@ #define SUN4I_SPDIF_SAMFREQ_176_4KHZ 0xc #define SUN4I_SPDIF_SAMFREQ_192KHZ 0xe +/** + * struct sun4i_spdif_quirks - Differences between SoC variants. + * + * @reg_dac_tx_data: TX FIFO offset for DMA config. + * @has_reset: SoC needs reset deasserted. + */ +struct sun4i_spdif_quirks { + unsigned int reg_dac_txdata; + bool has_reset; +}; + struct sun4i_spdif_dev { struct platform_device *pdev; struct clk *spdif_clk; @@ -405,11 +416,6 @@ static struct snd_soc_dai_driver sun4i_spdif_dai = { .name = "spdif", }; -struct sun4i_spdif_quirks { - unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */ - bool has_reset; -}; - static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = { .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, }; From f6a86b436b265888a0be92e29ceaf0494101e277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 27 May 2019 22:06:23 +0200 Subject: [PATCH 111/626] ASoC: sun4i-spdif: Add TX fifo bit flush quirks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allwinner H6 has a different bit to flush the TX FIFO. Add a quirks to prepare introduction of H6 SoC. Signed-off-by: Clément Péron Acked-by: Maxime Ripard Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-spdif.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index b6c66a62e915..045d0cc4b62a 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -166,10 +166,12 @@ * * @reg_dac_tx_data: TX FIFO offset for DMA config. * @has_reset: SoC needs reset deasserted. + * @val_fctl_ftx: TX FIFO flush bitmask. */ struct sun4i_spdif_quirks { unsigned int reg_dac_txdata; bool has_reset; + unsigned int val_fctl_ftx; }; struct sun4i_spdif_dev { @@ -180,16 +182,19 @@ struct sun4i_spdif_dev { struct snd_soc_dai_driver cpu_dai_drv; struct regmap *regmap; struct snd_dmaengine_dai_dma_data dma_params_tx; + const struct sun4i_spdif_quirks *quirks; }; static void sun4i_spdif_configure(struct sun4i_spdif_dev *host) { + const struct sun4i_spdif_quirks *quirks = host->quirks; + /* soft reset SPDIF */ regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET); /* flush TX FIFO */ regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, - SUN4I_SPDIF_FCTL_FTX, SUN4I_SPDIF_FCTL_FTX); + quirks->val_fctl_ftx, quirks->val_fctl_ftx); /* clear TX counter */ regmap_write(host->regmap, SUN4I_SPDIF_TXCNT, 0); @@ -418,15 +423,18 @@ static struct snd_soc_dai_driver sun4i_spdif_dai = { static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = { .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, }; static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = { .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, .has_reset = true, }; static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = { .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, .has_reset = true, }; @@ -507,6 +515,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); return -ENODEV; } + host->quirks = quirks; host->regmap = devm_regmap_init_mmio(&pdev->dev, base, &sun4i_spdif_regmap_config); From 99a12c766e20f76eb47819fd56ff60b2010048c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 27 May 2019 22:06:24 +0200 Subject: [PATCH 112/626] ASoC: sun4i-spdif: Add support for H6 SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allwinner H6 has a different mapping for the fifo register controller. Actually only the fifo TX bit is used in the drivers. Use the freshly introduced quirks to make this drivers compatible with the Allwinner H6. Signed-off-by: Clément Péron Acked-by: Maxime Ripard Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-spdif.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index 045d0cc4b62a..54c09346d298 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -75,6 +75,18 @@ #define SUN4I_SPDIF_FCTL_RXOM(v) ((v) << 0) #define SUN4I_SPDIF_FCTL_RXOM_MASK GENMASK(1, 0) +#define SUN50I_H6_SPDIF_FCTL (0x14) + #define SUN50I_H6_SPDIF_FCTL_HUB_EN BIT(31) + #define SUN50I_H6_SPDIF_FCTL_FTX BIT(30) + #define SUN50I_H6_SPDIF_FCTL_FRX BIT(29) + #define SUN50I_H6_SPDIF_FCTL_TXTL(v) ((v) << 12) + #define SUN50I_H6_SPDIF_FCTL_TXTL_MASK GENMASK(19, 12) + #define SUN50I_H6_SPDIF_FCTL_RXTL(v) ((v) << 4) + #define SUN50I_H6_SPDIF_FCTL_RXTL_MASK GENMASK(10, 4) + #define SUN50I_H6_SPDIF_FCTL_TXIM BIT(2) + #define SUN50I_H6_SPDIF_FCTL_RXOM(v) ((v) << 0) + #define SUN50I_H6_SPDIF_FCTL_RXOM_MASK GENMASK(1, 0) + #define SUN4I_SPDIF_FSTA (0x18) #define SUN4I_SPDIF_FSTA_TXE BIT(14) #define SUN4I_SPDIF_FSTA_TXECNTSHT (8) @@ -438,6 +450,12 @@ static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = { .has_reset = true, }; +static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = { + .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX, + .has_reset = true, +}; + static const struct of_device_id sun4i_spdif_of_match[] = { { .compatible = "allwinner,sun4i-a10-spdif", @@ -451,6 +469,10 @@ static const struct of_device_id sun4i_spdif_of_match[] = { .compatible = "allwinner,sun8i-h3-spdif", .data = &sun8i_h3_spdif_quirks, }, + { + .compatible = "allwinner,sun50i-h6-spdif", + .data = &sun50i_h6_spdif_quirks, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); From a54988113985ca22e414e132054f234fc8a92604 Mon Sep 17 00:00:00 2001 From: Gen Zhang Date: Wed, 29 May 2019 09:53:05 +0800 Subject: [PATCH 113/626] wcd9335: fix a incorrect use of kstrndup() In wcd9335_codec_enable_dec(), 'widget_name' is allocated by kstrndup(). However, according to doc: "Note: Use kmemdup_nul() instead if the size is known exactly." So we should use kmemdup_nul() here instead of kstrndup(). Signed-off-by: Gen Zhang Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index a04a7cedd99d..85737fe54474 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -2734,7 +2734,7 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w, char *dec; u8 hpf_coff_freq; - widget_name = kstrndup(w->name, 15, GFP_KERNEL); + widget_name = kmemdup_nul(w->name, 15, GFP_KERNEL); if (!widget_name) return -ENOMEM; From 17fc24875da1bef4650cf007edae3b2e26d2fa4e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 28 May 2019 11:28:22 -0500 Subject: [PATCH 114/626] ASoC: Intel: sof-rt5682: fix undefined references with Baytrail-only support The sof-rt5682 machine driver supports both legacy Baytrail devices and more recent ApolloLake/CometLake platforms. When only Baytrail is selected, the compilation fails with the following errors: ERROR: "hdac_hdmi_jack_port_init" [sound/soc/intel/boards/snd-soc-sof_rt5682.ko] undefined! ERROR: "hdac_hdmi_jack_init" [sound/soc/intel/boards/snd-soc-sof_rt5682.ko] undefined! Fix by selecting SND_SOC_HDAC_HDMI unconditionally. The code for HDMI support is not reachable on Baytrail so this change has no functional impact. Fixes: f70abd75b7c6 ("ASoC: Intel: add sof-rt5682 machine driver") Reported-by: kbuild test robot Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 59e366edc16b..317ee1e8c8c6 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -402,7 +402,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH (SND_SOC_SOF_BAYTRAIL && X86_INTEL_LPSS) select SND_SOC_RT5682 select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI if SND_SOC_SOF_HDA_COMMON + select SND_SOC_HDAC_HDMI help This adds support for ASoC machine driver for SOF platforms with rt5682 codec. From 7cda6223503d592f980a222811355ab07611b821 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 29 May 2019 11:30:02 +0800 Subject: [PATCH 115/626] ASoC: cs42xx8: Fix build error with CONFIG_GPIOLIB is not set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit config: x86_64-randconfig-x000201921-201921 compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 reproduce: make ARCH=x86_64 sound/soc/codecs/cs42xx8.c: In function ‘cs42xx8_probe’: sound/soc/codecs/cs42xx8.c:472:25: error: implicit declaration of function ‘devm_gpiod_get_optional’; did you mean ‘devm_clk_get_optional’? [-Werror=implicit-function-declaration] cs42xx8->gpiod_reset = devm_gpiod_get_optional(dev, "reset", ^~~~~~~~~~~~~~~~~~~~~~~ devm_clk_get_optional sound/soc/codecs/cs42xx8.c:473:8: error: ‘GPIOD_OUT_HIGH’ undeclared (first use in this function); did you mean ‘GPIOF_INIT_HIGH’? GPIOD_OUT_HIGH); ^~~~~~~~~~~~~~ GPIOF_INIT_HIGH sound/soc/codecs/cs42xx8.c:473:8: note: each undeclared identifier is reported only once for each function it appears in sound/soc/codecs/cs42xx8.c:477:2: error: implicit declaration of function ‘gpiod_set_value_cansleep’; did you mean ‘gpio_set_value_cansleep’? [-Werror=implicit-function-declaration] gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0); ^~~~~~~~~~~~~~~~~~~~~~~~ gpio_set_value_cansleep Fixes: bfe95dfa4dac ("ASoC: cs42xx8: Add reset gpio handling") Reported-by: kbuild test robot Signed-off-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/codecs/cs42xx8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index b377cddaf2e6..6203f54d9f25 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include From b19671d6caf1ac393681864d5d85dda9fa99a448 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 29 May 2019 14:22:14 +0800 Subject: [PATCH 116/626] ASoC: core: use component driver name as component name fmt_single_name() uses device name to determine component name. If multiple components bind to the same device, the debugfs creation in soc_init_component_debugfs() would fail due to duplicated entity names. Name provided by component driver is unique enough to represent each component. Use component driver name as the component name to avoid name duplication. Signed-off-by: Tzung-Bi Shih Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ce8c057bcd5b..5f83e2f19801 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3106,7 +3106,10 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, { struct snd_soc_dapm_context *dapm; - component->name = fmt_single_name(dev, &component->id); + if (driver->name) + component->name = kstrdup(driver->name, GFP_KERNEL); + else + component->name = fmt_single_name(dev, &component->id); if (!component->name) { dev_err(dev, "ASoC: Failed to allocate name\n"); return -ENOMEM; From ee8829dc609c5c4a425b4a65fbb4cd56fb82f1f4 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 30 May 2019 04:59:00 +0800 Subject: [PATCH 117/626] ALSA: hda: fix: lock reg_lock before calling snd_hdac_bus_update_rirb The patch is to fix commit 5e13cf6cd64c (ALSA: hda: add polling mode in snd_hdac_bus_get_response) spin_lock_irq should be called before snd_hdac_bus_update_rirb. Fixes: 5e13cf6cd64c ("ALSA: hda: add polling mode in snd_hdac_bus_get_response") Signed-off-by: Bard Liao Signed-off-by: Takashi Iwai --- sound/hda/hdac_controller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index a16ac31bda83..d6a91429c058 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -239,9 +239,9 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, timeout = jiffies + msecs_to_jiffies(1000); for (loopcounter = 0;; loopcounter++) { + spin_lock_irq(&bus->reg_lock); if (bus->polling_mode) snd_hdac_bus_update_rirb(bus); - spin_lock_irq(&bus->reg_lock); if (!bus->rirb.cmds[addr]) { if (res) *res = bus->rirb.res[addr]; /* the last value */ From f499edf9fa90f184af9f457fd0912a788754af25 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 29 May 2019 12:30:48 -0700 Subject: [PATCH 118/626] ASoC: rt5677: Add missing voice activation register definitions Most of the voice activation definitions were missing, they will be needed for when hotwording is added. Also the source bits are only 2 wide not 3 and needed to be corrected. Signed-off-by: Curtis Malainey Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 11a2ffceec3b..076e5161d8da 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h @@ -1456,9 +1456,37 @@ #define RT5677_I2S4_CLK_SEL_MASK (0xf) #define RT5677_I2S4_CLK_SEL_SFT 0 +/* VAD Function Control 1 (0x9c) */ +#define RT5677_VAD_MIN_DUR_MASK (0x3 << 13) +#define RT5677_VAD_MIN_DUR_SFT 13 +#define RT5677_VAD_ADPCM_BYPASS (1 << 10) +#define RT5677_VAD_ADPCM_BYPASS_BIT 10 +#define RT5677_VAD_FG2ENC (1 << 9) +#define RT5677_VAD_FG2ENC_BIT 9 +#define RT5677_VAD_BUF_OW (1 << 8) +#define RT5677_VAD_BUF_OW_BIT 8 +#define RT5677_VAD_CLR_FLAG (1 << 7) +#define RT5677_VAD_CLR_FLAG_BIT 7 +#define RT5677_VAD_BUF_POP (1 << 6) +#define RT5677_VAD_BUF_POP_BIT 6 +#define RT5677_VAD_BUF_PUSH (1 << 5) +#define RT5677_VAD_BUF_PUSH_BIT 5 +#define RT5677_VAD_DET_ENABLE (1 << 4) +#define RT5677_VAD_DET_ENABLE_BIT 4 +#define RT5677_VAD_FUNC_ENABLE (1 << 3) +#define RT5677_VAD_FUNC_ENABLE_BIT 3 +#define RT5677_VAD_FUNC_RESET (1 << 2) +#define RT5677_VAD_FUNC_RESET_BIT 2 + /* VAD Function Control 4 (0x9f) */ -#define RT5677_VAD_SRC_MASK (0x7 << 8) +#define RT5677_VAD_OUT_SRC_RATE_MASK (0x1 << 11) +#define RT5677_VAD_OUT_SRC_RATE_SFT 11 +#define RT5677_VAD_OUT_SRC_MASK (0x1 << 10) +#define RT5677_VAD_OUT_SRC_SFT 10 +#define RT5677_VAD_SRC_MASK (0x3 << 8) #define RT5677_VAD_SRC_SFT 8 +#define RT5677_VAD_LV_DIFF_MASK (0xff << 0) +#define RT5677_VAD_LV_DIFF_SFT 0 /* DSP InBound Control (0xa3) */ #define RT5677_IB01_SRC_MASK (0x7 << 12) From 536cfd2f375d36f4316c0b93bb9e0eaf78e0ef6c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 30 May 2019 06:50:11 -0500 Subject: [PATCH 119/626] ASoC: Intel: use common helpers to detect CPUs We have duplicated code in multiple locations (atom, machine drivers, SOF) to detect Baytrail, Cherrytrail and other SOCs. This is not very elegant, and introduces dependencies on CONFIG_X86 that prevent COMPILE_TEST from working. Add common helpers to provide same functionality in a cleaner way. This will also help support the DMI-based quirks being introduced to handle SOF/SST autodetection. Reviewed-by: Takashi Iwai Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_acpi.c | 65 +--------- sound/soc/intel/boards/bxt_da7219_max98357a.c | 11 +- sound/soc/intel/boards/bytcht_es8316.c | 12 +- sound/soc/intel/boards/bytcr_rt5640.c | 16 +-- sound/soc/intel/boards/bytcr_rt5651.c | 17 +-- sound/soc/intel/boards/cht_bsw_rt5645.c | 16 +-- sound/soc/intel/boards/sof_rt5682.c | 11 +- sound/soc/intel/common/soc-intel-quirks.h | 115 ++++++++++++++++++ sound/soc/sof/sof-acpi-dev.c | 57 +-------- 9 files changed, 135 insertions(+), 185 deletions(-) create mode 100644 sound/soc/intel/common/soc-intel-quirks.h diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index ae17ce4677a5..06c4a2da900c 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -38,12 +38,11 @@ #include #include #include -#include -#include #include #include #include "../sst-mfld-platform.h" #include "../../common/sst-dsp.h" +#include "../../common/soc-intel-quirks.h" #include "sst.h" /* LPE viewpoint addresses */ @@ -243,64 +242,6 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) return 0; } -static int is_byt(void) -{ - bool status = false; - static const struct x86_cpu_id cpu_ids[] = { - { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ - {} - }; - if (x86_match_cpu(cpu_ids)) - status = true; - return status; -} - -static bool is_byt_cr(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - int status = 0; - - if (!is_byt()) - return false; - - if (iosf_mbi_available()) { - u32 bios_status; - status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */ - MBI_REG_READ, /* 0x10 */ - 0x006, /* BIOS_CONFIG */ - &bios_status); - - if (status) { - dev_err(dev, "could not read PUNIT BIOS_CONFIG\n"); - } else { - /* bits 26:27 mirror PMIC options */ - bios_status = (bios_status >> 26) & 3; - - if (bios_status == 1 || bios_status == 3) { - dev_info(dev, "Detected Baytrail-CR platform\n"); - return true; - } - - dev_info(dev, "BYT-CR not detected\n"); - } - } else { - dev_info(dev, "IOSF_MBI not available, no BYT-CR detection\n"); - } - - if (platform_get_resource(pdev, IORESOURCE_IRQ, 5) == NULL) { - /* - * Some devices detected as BYT-T have only a single IRQ listed, - * causing platform_get_irq with index 5 to return -ENXIO. - * The correct IRQ in this case is at index 0, as on BYT-CR. - */ - dev_info(dev, "Falling back to Baytrail-CR platform\n"); - return true; - } - - return false; -} - - static int sst_acpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -325,7 +266,7 @@ static int sst_acpi_probe(struct platform_device *pdev) return -ENODEV; } - if (is_byt()) + if (soc_intel_is_byt()) mach->pdata = &byt_rvp_platform_data; else mach->pdata = &chv_platform_data; @@ -343,7 +284,7 @@ static int sst_acpi_probe(struct platform_device *pdev) if (ret < 0) return ret; - if (is_byt_cr(pdev)) { + if (soc_intel_is_byt_cr(pdev)) { /* override resource info */ byt_rvp_platform_data.res_info = &bytcr_res_info; } diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 5cadb7f654f3..4ee769a86201 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -16,7 +16,6 @@ * GNU General Public License for more details. */ -#include #include #include #include @@ -29,6 +28,7 @@ #include "../../codecs/hdac_hdmi.h" #include "../../codecs/da7219.h" #include "../../codecs/da7219-aad.h" +#include "../common/soc-intel-quirks.h" #define BXT_DIALOG_CODEC_DAI "da7219-hifi" #define BXT_MAXIM_CODEC_DAI "HiFi" @@ -568,11 +568,6 @@ static struct snd_soc_dai_link broxton_dais[] = { }, }; -static const struct x86_cpu_id glk_ids[] = { - { X86_VENDOR_INTEL, 6, 0x7A }, /* Geminilake CPU_ID */ - {} -}; - #define NAME_SIZE 32 static int bxt_card_late_probe(struct snd_soc_card *card) { @@ -582,7 +577,7 @@ static int bxt_card_late_probe(struct snd_soc_card *card) int err, i = 0; char jack_name[NAME_SIZE]; - if (x86_match_cpu(glk_ids)) + if (soc_intel_is_glk()) snd_soc_dapm_add_routes(&card->dapm, gemini_map, ARRAY_SIZE(gemini_map)); else @@ -645,7 +640,7 @@ static int broxton_audio_probe(struct platform_device *pdev) broxton_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&broxton_audio_card, ctx); - if (x86_match_cpu(glk_ids)) { + if (soc_intel_is_glk()) { unsigned int i; broxton_audio_card.name = "glkda7219max"; diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index e8c585ffd04d..d08715ac3945 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include #include #include @@ -40,6 +38,7 @@ #include #include "../atom/sst-atom-controls.h" #include "../common/sst-dsp.h" +#include "../common/soc-intel-quirks.h" /* jd-inv + terminating entry */ #define MAX_NO_PROPS 2 @@ -430,11 +429,6 @@ static struct snd_soc_card byt_cht_es8316_card = { .resume_post = byt_cht_es8316_resume, }; -static const struct x86_cpu_id baytrail_cpu_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, /* Valleyview */ - {} -}; - static const struct acpi_gpio_params first_gpio = { 0, 0, false }; static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = { @@ -506,8 +500,8 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) dmi_id = dmi_first_match(byt_cht_es8316_quirk_table); if (dmi_id) { quirk = (unsigned long)dmi_id->driver_data; - } else if (x86_match_cpu(baytrail_cpu_ids) && - mach->mach_params.acpi_ipc_irq_index == 0) { + } else if (soc_intel_is_byt() && + mach->mach_params.acpi_ipc_irq_index == 0) { /* On BYTCR default to SSP0, internal-mic-in2-map, mono-spk */ quirk = BYT_CHT_ES8316_SSP0 | BYT_CHT_ES8316_INTMIC_IN2_MAP | BYT_CHT_ES8316_MONO_SPEAKER; diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index dc22df9a99fb..7aae7b78efba 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -38,6 +37,7 @@ #include "../../codecs/rt5640.h" #include "../atom/sst-atom-controls.h" #include "../common/sst-dsp.h" +#include "../common/soc-intel-quirks.h" enum { BYT_RT5640_DMIC1_MAP, @@ -1130,18 +1130,6 @@ static struct snd_soc_card byt_rt5640_card = { .resume_post = byt_rt5640_resume, }; -static bool is_valleyview(void) -{ - static const struct x86_cpu_id cpu_ids[] = { - { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ - {} - }; - - if (!x86_match_cpu(cpu_ids)) - return false; - return true; -} - struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ u64 aif_value; /* 1: AIF1, 2: AIF2 */ u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ @@ -1190,7 +1178,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) * swap SSP0 if bytcr is detected * (will be overridden if DMI quirk is detected) */ - if (is_valleyview()) { + if (soc_intel_is_byt()) { if (mach->mach_params.acpi_ipc_irq_index == 0) is_bytcr = true; } diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index ca657c3e5726..6df6435ea394 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include #include #include @@ -39,6 +37,7 @@ #include #include "../../codecs/rt5651.h" #include "../atom/sst-atom-controls.h" +#include "../common/soc-intel-quirks.h" enum { BYT_RT5651_DMIC_MAP, @@ -852,16 +851,6 @@ static struct snd_soc_card byt_rt5651_card = { .resume_post = byt_rt5651_resume, }; -static const struct x86_cpu_id baytrail_cpu_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, /* Valleyview */ - {} -}; - -static const struct x86_cpu_id cherrytrail_cpu_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, /* Braswell */ - {} -}; - static const struct acpi_gpio_params ext_amp_enable_gpios = { 0, 0, false }; static const struct acpi_gpio_mapping cht_rt5651_gpios[] = { @@ -932,7 +921,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) * swap SSP0 if bytcr is detected * (will be overridden if DMI quirk is detected) */ - if (x86_match_cpu(baytrail_cpu_ids)) { + if (soc_intel_is_byt()) { if (mach->mach_params.acpi_ipc_irq_index == 0) is_bytcr = true; } @@ -1001,7 +990,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) } /* Cherry Trail devices use an external amplifier enable gpio */ - if (x86_match_cpu(cherrytrail_cpu_ids) && !byt_rt5651_gpios) + if (soc_intel_is_cht() && !byt_rt5651_gpios) byt_rt5651_gpios = cht_rt5651_gpios; if (byt_rt5651_gpios) { diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 32dbeaf1ab94..de5fe58ae3b4 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -34,6 +33,7 @@ #include #include "../../codecs/rt5645.h" #include "../atom/sst-atom-controls.h" +#include "../common/soc-intel-quirks.h" #define CHT_PLAT_CLK_3_HZ 19200000 #define CHT_CODEC_DAI1 "rt5645-aif1" @@ -509,18 +509,6 @@ static char cht_rt5645_codec_name[SND_ACPI_I2C_ID_LEN]; static char cht_rt5645_codec_aif_name[12]; /* = "rt5645-aif[1|2]" */ static char cht_rt5645_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ -static bool is_valleyview(void) -{ - static const struct x86_cpu_id cpu_ids[] = { - { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ - {} - }; - - if (!x86_match_cpu(cpu_ids)) - return false; - return true; -} - struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ u64 aif_value; /* 1: AIF1, 2: AIF2 */ u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ @@ -585,7 +573,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) * swap SSP0 if bytcr is detected * (will be overridden if DMI quirk is detected) */ - if (is_valleyview()) { + if (soc_intel_is_byt()) { if (mach->mach_params.acpi_ipc_irq_index == 0) is_bytcr = true; } diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index e441dc979966..355fd9730a44 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include #include #include @@ -21,6 +19,7 @@ #include #include "../../codecs/rt5682.h" #include "../../codecs/hdac_hdmi.h" +#include "../common/soc-intel-quirks.h" #define NAME_SIZE 32 @@ -304,12 +303,6 @@ static struct snd_soc_card sof_audio_card_rt5682 = { .late_probe = sof_card_late_probe, }; -static const struct x86_cpu_id legacy_cpi_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, /* Baytrail */ - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, /* Cherrytrail */ - {} -}; - static struct snd_soc_dai_link_component rt5682_component[] = { { .name = "i2c-10EC5682:00", @@ -498,7 +491,7 @@ static int sof_audio_probe(struct platform_device *pdev) if (!ctx) return -ENOMEM; - if (x86_match_cpu(legacy_cpi_ids)) { + if (soc_intel_is_byt() || soc_intel_is_cht()) { is_legacy_cpu = 1; dmic_num = 0; hdmi_num = 0; diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h new file mode 100644 index 000000000000..4718fd3cf636 --- /dev/null +++ b/sound/soc/intel/common/soc-intel-quirks.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * soc-intel-quirks.h - prototypes for quirk autodetection + * + * Copyright (c) 2019, Intel Corporation. + * + */ + +#ifndef _SND_SOC_INTEL_QUIRKS_H +#define _SND_SOC_INTEL_QUIRKS_H + +#if IS_ENABLED(CONFIG_X86) + +#include +#include +#include + +#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } + +#define SOC_INTEL_IS_CPU(soc, type) \ +static inline bool soc_intel_is_##soc(void) \ +{ \ + static const struct x86_cpu_id soc##_cpu_ids[] = { \ + ICPU(type), \ + {} \ + }; \ + const struct x86_cpu_id *id; \ + \ + id = x86_match_cpu(soc##_cpu_ids); \ + if (id) \ + return true; \ + return false; \ +} + +SOC_INTEL_IS_CPU(byt, INTEL_FAM6_ATOM_SILVERMONT); +SOC_INTEL_IS_CPU(cht, INTEL_FAM6_ATOM_AIRMONT); +SOC_INTEL_IS_CPU(apl, INTEL_FAM6_ATOM_GOLDMONT); +SOC_INTEL_IS_CPU(glk, INTEL_FAM6_ATOM_GOLDMONT_PLUS); + +static inline bool soc_intel_is_byt_cr(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int status = 0; + + if (!soc_intel_is_byt()) + return false; + + if (iosf_mbi_available()) { + u32 bios_status; + + status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */ + MBI_REG_READ, /* 0x10 */ + 0x006, /* BIOS_CONFIG */ + &bios_status); + + if (status) { + dev_err(dev, "could not read PUNIT BIOS_CONFIG\n"); + } else { + /* bits 26:27 mirror PMIC options */ + bios_status = (bios_status >> 26) & 3; + + if (bios_status == 1 || bios_status == 3) { + dev_info(dev, "Detected Baytrail-CR platform\n"); + return true; + } + + dev_info(dev, "BYT-CR not detected\n"); + } + } else { + dev_info(dev, "IOSF_MBI not available, no BYT-CR detection\n"); + } + + if (!platform_get_resource(pdev, IORESOURCE_IRQ, 5)) { + /* + * Some devices detected as BYT-T have only a single IRQ listed, + * causing platform_get_irq with index 5 to return -ENXIO. + * The correct IRQ in this case is at index 0, as on BYT-CR. + */ + dev_info(dev, "Falling back to Baytrail-CR platform\n"); + return true; + } + + return false; +} + +#else + +static inline bool soc_intel_is_byt_cr(struct platform_device *pdev) +{ + return false; +} + +static inline bool soc_intel_is_byt(void) +{ + return false; +} + +static inline bool soc_intel_is_cht(void) +{ + return false; +} + +static inline bool soc_intel_is_apl(void) +{ + return false; +} + +static inline bool soc_intel_is_glk(void) +{ + return false; +} + +#endif + + #endif /* _SND_SOC_INTEL_QUIRKS_H */ diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index e9cf69874b5b..c8dafb1ac54e 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -15,10 +15,7 @@ #include #include #include -#ifdef CONFIG_X86 -#include -#endif - +#include "../intel/common/soc-intel-quirks.h" #include "ops.h" /* platform specific devices */ @@ -99,56 +96,6 @@ static const struct sof_dev_desc sof_acpi_baytrail_desc = { .arch_ops = &sof_xtensa_arch_ops }; -#ifdef CONFIG_X86 /* TODO: move this to common helper */ - -static bool is_byt_cr(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - int status; - - if (iosf_mbi_available()) { - u32 bios_status; - status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */ - MBI_REG_READ, /* 0x10 */ - 0x006, /* BIOS_CONFIG */ - &bios_status); - - if (status) { - dev_err(dev, "could not read PUNIT BIOS_CONFIG\n"); - } else { - /* bits 26:27 mirror PMIC options */ - bios_status = (bios_status >> 26) & 3; - - if (bios_status == 1 || bios_status == 3) { - dev_info(dev, "Detected Baytrail-CR platform\n"); - return true; - } - - dev_info(dev, "BYT-CR not detected\n"); - } - } else { - dev_info(dev, "IOSF_MBI not available, no BYT-CR detection\n"); - } - - if (platform_get_resource(pdev, IORESOURCE_IRQ, 5) == NULL) { - /* - * Some devices detected as BYT-T have only a single IRQ listed, - * causing platform_get_irq with index 5 to return -ENXIO. - * The correct IRQ in this case is at index 0, as on BYT-CR. - */ - dev_info(dev, "Falling back to Baytrail-CR platform\n"); - return true; - } - - return false; -} -#else -static int is_byt_cr(struct platform_device *pdev) -{ - return 0; -} -#endif - static const struct sof_dev_desc sof_acpi_cherrytrail_desc = { .machines = snd_soc_acpi_intel_cherrytrail_machines, .resindex_lpe_base = 0, @@ -200,7 +147,7 @@ static int sof_acpi_probe(struct platform_device *pdev) return -ENODEV; #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) - if (desc == &sof_acpi_baytrail_desc && is_byt_cr(pdev)) + if (desc == &sof_acpi_baytrail_desc && soc_intel_is_byt_cr(pdev)) desc = &sof_acpi_baytrailcr_desc; #endif From 2c79eeb1aaf2bf0a6d9bb4732596f7dc147cab4d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 May 2019 06:50:12 -0500 Subject: [PATCH 120/626] ASoc: fix sound/soc/intel/skylake/slk-ssp-clk.c build error on IA64 skl-ssp-clk.c does not build on IA64 because the driver uses the common clock interface, so make the driver depend on COMMON_CLK. Fixes this build error: ../sound/soc/intel/skylake/skl-ssp-clk.c:26:16: error: field 'hw' has incomplete type struct clk_hw hw; ^~ [Corrections for SKL support by Pierre Bossart] Reported-by: kbuild test robot Signed-off-by: Randy Dunlap Signed-off-by: Pierre-Louis Bossart Cc: Mark Brown Cc: Liam Girdwood Cc: Jie Yang Cc: alsa-devel@alsa-project.org Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index b089ed3bf77f..a3cf47d09816 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -104,6 +104,7 @@ config SND_SST_ATOM_HIFI2_PLATFORM_ACPI config SND_SOC_INTEL_SKYLAKE tristate "All Skylake/SST Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKL select SND_SOC_INTEL_APL select SND_SOC_INTEL_KBL @@ -120,6 +121,7 @@ config SND_SOC_INTEL_SKYLAKE config SND_SOC_INTEL_SKL tristate "Skylake Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKYLAKE_FAMILY help If you have a Intel Skylake platform with the DSP enabled @@ -128,6 +130,7 @@ config SND_SOC_INTEL_SKL config SND_SOC_INTEL_APL tristate "Broxton/ApolloLake Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKYLAKE_FAMILY help If you have a Intel Broxton/ApolloLake platform with the DSP @@ -136,6 +139,7 @@ config SND_SOC_INTEL_APL config SND_SOC_INTEL_KBL tristate "Kabylake Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKYLAKE_FAMILY help If you have a Intel Kabylake platform with the DSP @@ -144,6 +148,7 @@ config SND_SOC_INTEL_KBL config SND_SOC_INTEL_GLK tristate "GeminiLake Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKYLAKE_FAMILY help If you have a Intel GeminiLake platform with the DSP @@ -152,6 +157,7 @@ config SND_SOC_INTEL_GLK config SND_SOC_INTEL_CNL tristate "CannonLake/WhiskyLake Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKYLAKE_FAMILY help If you have a Intel CNL/WHL platform with the DSP @@ -160,6 +166,7 @@ config SND_SOC_INTEL_CNL config SND_SOC_INTEL_CFL tristate "CoffeeLake Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKYLAKE_FAMILY help If you have a Intel CoffeeLake platform with the DSP @@ -168,6 +175,7 @@ config SND_SOC_INTEL_CFL config SND_SOC_INTEL_CML_H tristate "CometLake-H Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKYLAKE_FAMILY help If you have a Intel CometLake-H platform with the DSP @@ -176,6 +184,7 @@ config SND_SOC_INTEL_CML_H config SND_SOC_INTEL_CML_LP tristate "CometLake-LP Platforms" depends on PCI && ACPI + depends on COMMON_CLK select SND_SOC_INTEL_SKYLAKE_FAMILY help If you have a Intel CometLake-LP platform with the DSP From 0d365acbbe295a67df5e1dc1e3661dc37390dd58 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 30 May 2019 06:50:13 -0500 Subject: [PATCH 121/626] ASoC: Intel: boards: remove dependency on asm/platform_sst_audio.h This is not needed. Probably a copy/paste that was never removed. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_cx2072x.c | 1 - sound/soc/intel/boards/bytcht_da7213.c | 1 - sound/soc/intel/boards/bytcht_es8316.c | 1 - 3 files changed, 3 deletions(-) diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index b21b0e7f981a..4b985b393dae 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index 4decba338156..9091ee697fbe 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index d08715ac3945..1f319b2a835f 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include From 8fe751d8fd5cbf19e9d7852c5b7d8ed818be1934 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 30 May 2019 06:50:14 -0500 Subject: [PATCH 122/626] ASoC: Intel: boards: Add COMPILE_TEST for new machine drivers We recently added COMPILE_TEST but new machine drivers were not updated. Fix. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 317ee1e8c8c6..41649dc1c5e0 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -157,7 +157,8 @@ config SND_SOC_INTEL_CHT_BSW_NAU8824_MACH config SND_SOC_INTEL_BYT_CHT_CX2072X_MACH tristate "Baytrail & Cherrytrail with CX2072X codec" - depends on X86_INTEL_LPSS && I2C && ACPI + depends on I2C && ACPI + depends on X86_INTEL_LPSS || COMPILE_TEST select SND_SOC_ACPI select SND_SOC_CX2072X help @@ -398,8 +399,8 @@ if SND_SOC_SOF_HDA_COMMON || SND_SOC_SOF_BAYTRAIL config SND_SOC_INTEL_SOF_RT5682_MACH tristate "SOF with rt5682 codec in I2S Mode" depends on I2C && ACPI - depends on (SND_SOC_SOF_HDA_COMMON && MFD_INTEL_LPSS) ||\ - (SND_SOC_SOF_BAYTRAIL && X86_INTEL_LPSS) + depends on (SND_SOC_SOF_HDA_COMMON && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ + (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) select SND_SOC_RT5682 select SND_SOC_DMIC select SND_SOC_HDAC_HDMI From e13ef82a9ab83dd21d8dd43ef9f5e8bf5b101106 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 30 May 2019 06:50:15 -0500 Subject: [PATCH 123/626] ASoC: SOF: add COMPILE_TEST for PCI options Add COMPILE_TEST and use IS_ENABLED(CONFIG_PCI) to sort out cross-compilation issues. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 2 +- sound/soc/sof/intel/hda.c | 13 +++++++++++-- sound/soc/sof/sof-pci-dev.c | 4 ++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index a9a1d502daae..ca3ad3362478 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -10,7 +10,7 @@ if SND_SOC_SOF_TOPLEVEL config SND_SOC_SOF_PCI tristate "SOF PCI enumeration support" - depends on PCI + depends on PCI || COMPILE_TEST select SND_SOC_SOF select SND_SOC_ACPI if ACPI select SND_SOC_SOF_OPTIONS diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7e3980a2f7ba..5378d47a55fd 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -506,7 +506,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * TODO: support interrupt mode selection with kernel parameter * support msi multiple vectors */ +#if IS_ENABLED(CONFIG_PCI) ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI); +#endif if (ret < 0) { dev_info(sdev->dev, "use legacy interrupt mode\n"); /* @@ -518,7 +520,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->msi_enabled = 0; } else { dev_info(sdev->dev, "use msi interrupt mode\n"); +#if IS_ENABLED(CONFIG_PCI) hdev->irq = pci_irq_vector(pci, 0); +#endif /* ipc irq number is the same of hda irq */ sdev->ipc_irq = hdev->irq; sdev->msi_enabled = 1; @@ -622,8 +626,10 @@ free_ipc_irq: free_hda_irq: free_irq(hdev->irq, bus); free_irq_vector: +#if IS_ENABLED(CONFIG_PCI) if (sdev->msi_enabled) pci_free_irq_vectors(pci); +#endif free_streams: hda_dsp_stream_free(sdev); /* dsp_unmap: not currently used */ @@ -638,7 +644,6 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); - struct pci_dev *pci = to_pci_dev(sdev->dev); const struct sof_intel_dsp_desc *chip = hda->desc; #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) @@ -667,8 +672,12 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) free_irq(sdev->ipc_irq, sdev); free_irq(hda->irq, bus); - if (sdev->msi_enabled) +#if IS_ENABLED(CONFIG_PCI) + if (sdev->msi_enabled) { + struct pci_dev *pci = to_pci_dev(sdev->dev); pci_free_irq_vectors(pci); + } +#endif hda_dsp_stream_free(sdev); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index e2b19782f01a..ab58d4f9119f 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -251,9 +251,11 @@ static int sof_pci_probe(struct pci_dev *pci, if (!sof_pdata) return -ENOMEM; +#if IS_ENABLED(CONFIG_PCI) ret = pcim_enable_device(pci); if (ret < 0) return ret; +#endif ret = pci_request_regions(pci, "Audio DSP"); if (ret < 0) @@ -386,6 +388,7 @@ static const struct pci_device_id sof_pci_ids[] = { }; MODULE_DEVICE_TABLE(pci, sof_pci_ids); +#if IS_ENABLED(CONFIG_PCI) /* pci_driver definition */ static struct pci_driver snd_sof_pci_driver = { .name = "sof-audio-pci", @@ -397,5 +400,6 @@ static struct pci_driver snd_sof_pci_driver = { }, }; module_pci_driver(snd_sof_pci_driver); +#endif MODULE_LICENSE("Dual BSD/GPL"); From 970c43d1783539b75a5e234ff5e51fc5c888112f Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Fri, 24 May 2019 14:09:25 -0500 Subject: [PATCH 124/626] ASoC: SOF: Intel: hda: use the defined ppcap functions There are already defined ppcap and ppcap interrupt functions, use the already defined functions for easy code read. Fixes: 8a300c8fb17 ("ASoC: SOF: Intel: Add HDA controller for Intel DSP") Reviewed-by: Takashi Iwai Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index b1f4db0a6895..92c546e93400 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -544,13 +544,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) goto free_ipc_irq; - /* enable DSP features */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_GPROCEN, SOF_HDA_PPCTL_GPROCEN); - - /* enable DSP IRQ */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_PIE, SOF_HDA_PPCTL_PIE); + /* enable ppcap interrupt */ + hda_dsp_ctrl_ppcap_enable(sdev, true); + hda_dsp_ctrl_ppcap_int_enable(sdev, true); /* initialize waitq for code loading */ init_waitqueue_head(&sdev->waitq); From 65be9580885e4c14af1448b5bac95517c52a7ad3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 31 May 2019 11:44:44 +0200 Subject: [PATCH 125/626] ALSA: control: Use struct_size() For code simplification and safety, use struct_size() macro for calculating the snd_kcontrol object size with the variable array. Signed-off-by: Takashi Iwai --- sound/core/control.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/core/control.c b/sound/core/control.c index a5cc9a874062..04eb1a15ffb4 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -211,16 +211,12 @@ EXPORT_SYMBOL(snd_ctl_notify); static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count, unsigned int access, struct snd_ctl_file *file) { - unsigned int size; unsigned int idx; if (count == 0 || count > MAX_CONTROL_COUNT) return -EINVAL; - size = sizeof(struct snd_kcontrol); - size += sizeof(struct snd_kcontrol_volatile) * count; - - *kctl = kzalloc(size, GFP_KERNEL); + *kctl = kzalloc(struct_size(*kctl, vd, count), GFP_KERNEL); if (!*kctl) return -ENOMEM; From a2d4560f0be9a48cd342992fbec0688ea05d564b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 31 May 2019 11:46:49 +0200 Subject: [PATCH 126/626] ALSA: hda: Use struct_size() For code simplification and safety, use struct_size() macro for calculating the hda_conn_list object size with the variable array. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b20eb7fc83eb..d0f1dbcfbda4 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -122,7 +122,7 @@ static int add_conn_list(struct hda_codec *codec, hda_nid_t nid, int len, { struct hda_conn_list *p; - p = kmalloc(sizeof(*p) + len * sizeof(hda_nid_t), GFP_KERNEL); + p = kmalloc(struct_size(p, conns, len), GFP_KERNEL); if (!p) return -ENOMEM; p->len = len; From e046b64b1547e2dc1ac27e0a5ac57e55213e16f1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 31 May 2019 11:47:24 +0200 Subject: [PATCH 127/626] ALSA: hda/ca0132: Use struct_size() For code simplification and safety, use struct_size() macro for calculating the dsp_image_seg object size. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index e1ebc6d5f382..de61179c91e2 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -2731,7 +2731,7 @@ static bool is_last(const struct dsp_image_seg *p) static size_t dsp_sizeof(const struct dsp_image_seg *p) { - return sizeof(*p) + p->count*sizeof(u32); + return struct_size(p, data, p->count); } static const struct dsp_image_seg *get_next_seg_ptr( From 1d9c95c1896256a64e3a8d825f9e78cc79d29ebb Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 3 Jun 2019 10:16:34 +0200 Subject: [PATCH 128/626] ASoC: stm32: sai: manage identification registers Add support of identification registers in STM32 SAI. Signed-off-by: Olivier Moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai.c | 44 ++++++++++++++++++++++++---- sound/soc/stm/stm32_sai.h | 54 ++++++++++++++++++++++++++--------- sound/soc/stm/stm32_sai_sub.c | 14 +++++---- 3 files changed, 88 insertions(+), 24 deletions(-) diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 7550d5f08be3..98b29f712831 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -30,13 +30,20 @@ #include "stm32_sai.h" static const struct stm32_sai_conf stm32_sai_conf_f4 = { - .version = SAI_STM32F4, - .has_spdif = false, + .version = STM_SAI_STM32F4, + .fifo_size = 8, + .has_spdif_pdm = false, }; +/* + * Default settings for stm32 H7 socs and next. + * These default settings will be overridden if the soc provides + * support of hardware configuration registers. + */ static const struct stm32_sai_conf stm32_sai_conf_h7 = { - .version = SAI_STM32H7, - .has_spdif = true, + .version = STM_SAI_STM32H7, + .fifo_size = 8, + .has_spdif_pdm = true, }; static const struct of_device_id stm32_sai_ids[] = { @@ -157,6 +164,8 @@ static int stm32_sai_probe(struct platform_device *pdev) struct reset_control *rst; struct resource *res; const struct of_device_id *of_id; + u32 val; + int ret; sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); if (!sai) @@ -169,7 +178,8 @@ static int stm32_sai_probe(struct platform_device *pdev) of_id = of_match_device(stm32_sai_ids, &pdev->dev); if (of_id) - sai->conf = (struct stm32_sai_conf *)of_id->data; + memcpy(&sai->conf, (const struct stm32_sai_conf *)of_id->data, + sizeof(struct stm32_sai_conf)); else return -EINVAL; @@ -208,6 +218,30 @@ static int stm32_sai_probe(struct platform_device *pdev) reset_control_deassert(rst); } + /* Enable peripheral clock to allow register access */ + ret = clk_prepare_enable(sai->pclk); + if (ret) { + dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); + return ret; + } + + val = FIELD_GET(SAI_IDR_ID_MASK, + readl_relaxed(sai->base + STM_SAI_IDR)); + if (val == SAI_IPIDR_NUMBER) { + val = readl_relaxed(sai->base + STM_SAI_HWCFGR); + sai->conf.fifo_size = FIELD_GET(SAI_HWCFGR_FIFO_SIZE, val); + sai->conf.has_spdif_pdm = !!FIELD_GET(SAI_HWCFGR_SPDIF_PDM, + val); + + val = readl_relaxed(sai->base + STM_SAI_VERR); + sai->conf.version = val; + + dev_dbg(&pdev->dev, "SAI version: %lu.%lu registered\n", + FIELD_GET(SAI_VERR_MAJ_MASK, val), + FIELD_GET(SAI_VERR_MIN_MASK, val)); + } + clk_disable_unprepare(sai->pclk); + sai->pdev = pdev; sai->set_sync = &stm32_sai_set_sync; platform_set_drvdata(pdev, sai); diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h index 9c36a393ab7b..158c73f557f7 100644 --- a/sound/soc/stm/stm32_sai.h +++ b/sound/soc/stm/stm32_sai.h @@ -37,6 +37,12 @@ #define STM_SAI_PDMCR_REGX 0x40 #define STM_SAI_PDMLY_REGX 0x44 +/* Hardware configuration registers */ +#define STM_SAI_HWCFGR 0x3F0 +#define STM_SAI_VERR 0x3F4 +#define STM_SAI_IDR 0x3F8 +#define STM_SAI_SIDR 0x3FC + /******************** Bit definition for SAI_GCR register *******************/ #define SAI_GCR_SYNCIN_SHIFT 0 #define SAI_GCR_SYNCIN_WDTH 2 @@ -82,7 +88,7 @@ #define SAI_XCR1_NODIV BIT(SAI_XCR1_NODIV_SHIFT) #define SAI_XCR1_MCKDIV_SHIFT 20 -#define SAI_XCR1_MCKDIV_WIDTH(x) (((x) == SAI_STM32F4) ? 4 : 6) +#define SAI_XCR1_MCKDIV_WIDTH(x) (((x) == STM_SAI_STM32F4) ? 4 : 6) #define SAI_XCR1_MCKDIV_MASK(x) GENMASK((SAI_XCR1_MCKDIV_SHIFT + (x) - 1),\ SAI_XCR1_MCKDIV_SHIFT) #define SAI_XCR1_MCKDIV_SET(x) ((x) << SAI_XCR1_MCKDIV_SHIFT) @@ -234,8 +240,33 @@ #define SAI_PDMDLY_4R_MASK GENMASK(30, SAI_PDMDLY_4R_SHIFT) #define SAI_PDMDLY_4R_WIDTH 3 -#define STM_SAI_IS_F4(ip) ((ip)->conf->version == SAI_STM32F4) -#define STM_SAI_IS_H7(ip) ((ip)->conf->version == SAI_STM32H7) +/* Registers below apply to SAI version 2.1 and more */ + +/* Bit definition for SAI_HWCFGR register */ +#define SAI_HWCFGR_FIFO_SIZE GENMASK(7, 0) +#define SAI_HWCFGR_SPDIF_PDM GENMASK(11, 8) +#define SAI_HWCFGR_REGOUT GENMASK(19, 12) + +/* Bit definition for SAI_VERR register */ +#define SAI_VERR_MIN_MASK GENMASK(3, 0) +#define SAI_VERR_MAJ_MASK GENMASK(7, 4) + +/* Bit definition for SAI_IDR register */ +#define SAI_IDR_ID_MASK GENMASK(31, 0) + +/* Bit definition for SAI_SIDR register */ +#define SAI_SIDR_ID_MASK GENMASK(31, 0) + +#define SAI_IPIDR_NUMBER 0x00130031 + +/* SAI version numbers are 1.x for F4. Major version number set to 1 for F4 */ +#define STM_SAI_STM32F4 BIT(4) +/* Dummy version number for H7 socs and next */ +#define STM_SAI_STM32H7 0x0 + +#define STM_SAI_IS_F4(ip) ((ip)->conf.version == STM_SAI_STM32F4) +#define STM_SAI_HAS_SPDIF_PDM(ip)\ + ((ip)->pdata->conf.has_spdif_pdm) enum stm32_sai_syncout { STM_SAI_SYNC_OUT_NONE, @@ -243,19 +274,16 @@ enum stm32_sai_syncout { STM_SAI_SYNC_OUT_B, }; -enum stm32_sai_version { - SAI_STM32F4, - SAI_STM32H7 -}; - /** * struct stm32_sai_conf - SAI configuration * @version: SAI version - * @has_spdif: SAI S/PDIF support flag + * @fifo_size: SAI fifo size as words number + * @has_spdif_pdm: SAI S/PDIF and PDM features support flag */ struct stm32_sai_conf { - int version; - bool has_spdif; + u32 version; + u32 fifo_size; + bool has_spdif_pdm; }; /** @@ -265,7 +293,7 @@ struct stm32_sai_conf { * @pclk: SAI bus clock * @clk_x8k: SAI parent clock for sampling frequencies multiple of 8kHz * @clk_x11k: SAI parent clock for sampling frequencies multiple of 11kHz - * @version: SOC version + * @conf: SAI hardware capabitilites * @irq: SAI interrupt line * @set_sync: pointer to synchro mode configuration callback * @gcr: SAI Global Configuration Register @@ -276,7 +304,7 @@ struct stm32_sai_data { struct clk *pclk; struct clk *clk_x8k; struct clk *clk_x11k; - struct stm32_sai_conf *conf; + struct stm32_sai_conf conf; int irq; int (*set_sync)(struct stm32_sai_data *sai, struct device_node *np_provider, int synco, int synci); diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 2a74ce7c9440..7d27efb19380 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -45,7 +45,6 @@ #define SAI_DATASIZE_24 0x6 #define SAI_DATASIZE_32 0x7 -#define STM_SAI_FIFO_SIZE 8 #define STM_SAI_DAI_NAME_SIZE 15 #define STM_SAI_IS_PLAYBACK(ip) ((ip)->dir == SNDRV_PCM_STREAM_PLAYBACK) @@ -63,7 +62,8 @@ #define SAI_SYNC_EXTERNAL 0x2 #define STM_SAI_PROTOCOL_IS_SPDIF(ip) ((ip)->spdif) -#define STM_SAI_HAS_SPDIF(x) ((x)->pdata->conf->has_spdif) +#define STM_SAI_HAS_SPDIF(x) ((x)->pdata->conf.has_spdif_pdm) +#define STM_SAI_HAS_PDM(x) ((x)->pdata->conf.has_spdif_pdm) #define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4(sai->pdata)) #define SAI_IEC60958_BLOCK_FRAMES 192 @@ -274,7 +274,7 @@ static int stm32_sai_get_clk_div(struct stm32_sai_sub_data *sai, unsigned long input_rate, unsigned long output_rate) { - int version = sai->pdata->conf->version; + int version = sai->pdata->conf.version; int div; div = DIV_ROUND_CLOSEST(input_rate, output_rate); @@ -295,7 +295,7 @@ static int stm32_sai_get_clk_div(struct stm32_sai_sub_data *sai, static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai, unsigned int div) { - int version = sai->pdata->conf->version; + int version = sai->pdata->conf.version; int ret, cr1, mask; if (div > SAI_XCR1_MCKDIV_MAX(version)) { @@ -1148,6 +1148,8 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai) * constraints). */ sai->dma_params.maxburst = 4; + if (sai->pdata->conf.fifo_size < 8) + sai->dma_params.maxburst = 1; /* Buswidth will be set by framework at runtime */ sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; @@ -1315,8 +1317,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, sai->phys_addr = res->start; sai->regmap_config = &stm32_sai_sub_regmap_config_f4; - /* Note: PDM registers not available for H7 sub-block B */ - if (STM_SAI_IS_H7(sai->pdata) && STM_SAI_IS_SUB_A(sai)) + /* Note: PDM registers not available for sub-block B */ + if (STM_SAI_HAS_PDM(sai) && STM_SAI_IS_SUB_A(sai)) sai->regmap_config = &stm32_sai_sub_regmap_config_h7; sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "sai_ck", From 9d563eb95b81f32b9ffa4255033717484d50d06b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 31 May 2019 12:34:02 +0200 Subject: [PATCH 129/626] Revert "ASoC: core: use component driver name as component name" Using component driver as a name is not unique and it breaks audio in certain configurations, e.g. Hardkernel Odroid XU3 board where following components are registered: - "3830000.i2s" with driver name "snd_dmaengine_pcm" - "3830000.i2s-sec" with driver name "snd_dmaengine_pcm" - "3830000.i2s" with driver name "samsung-i2s" This reverts commit b19671d6caf1ac393681864d5d85dda9fa99a448. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2d3520fca613..7abb017a83f3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3113,10 +3113,7 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, { struct snd_soc_dapm_context *dapm; - if (driver->name) - component->name = kstrdup(driver->name, GFP_KERNEL); - else - component->name = fmt_single_name(dev, &component->id); + component->name = fmt_single_name(dev, &component->id); if (!component->name) { dev_err(dev, "ASoC: Failed to allocate name\n"); return -ENOMEM; From 5c9714f637365a84e05f0532cd9ae00c65b70dc1 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 3 Jun 2019 11:18:18 -0500 Subject: [PATCH 130/626] ASoC: SOF: add mode parameter for snd_sof_debugfs_buf_item Add mode parameter for snd_sof_debugfs_buf_item() to specify the mode while creating debugfs entries. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 4 ++-- sound/soc/sof/loader.c | 4 ++-- sound/soc/sof/sof-priv.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 55f1d808dba0..219c3becf670 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -161,7 +161,7 @@ EXPORT_SYMBOL_GPL(snd_sof_debugfs_io_item); /* create FS entry for debug files to expose kernel memory */ int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev, void *base, size_t size, - const char *name) + const char *name, mode_t mode) { struct snd_sof_dfsentry *dfse; @@ -177,7 +177,7 @@ int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev, dfse->size = size; dfse->sdev = sdev; - dfse->dfsentry = debugfs_create_file(name, 0444, sdev->debugfs_root, + dfse->dfsentry = debugfs_create_file(name, mode, sdev->debugfs_root, dfse, &sof_dfs_fops); if (!dfse->dfsentry) { /* can't rely on debugfs, only log error and keep going */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 16b016b76fd8..952a19091c58 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -335,11 +335,11 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) init_waitqueue_head(&sdev->boot_wait); sdev->boot_complete = false; - /* create fw_version debugfs to store boot version info */ + /* create read-only fw_version debugfs to store boot version info */ if (sdev->first_boot) { ret = snd_sof_debugfs_buf_item(sdev, &sdev->fw_version, sizeof(sdev->fw_version), - "fw_version"); + "fw_version", 0444); /* errors are only due to memory allocation, not debugfs */ if (ret < 0) { dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n"); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 01a6219c326b..ce22240cd93a 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -546,7 +546,7 @@ int snd_sof_debugfs_io_item(struct snd_sof_dev *sdev, enum sof_debugfs_access_type access_type); int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev, void *base, size_t size, - const char *name); + const char *name, mode_t mode); int snd_sof_trace_update_pos(struct snd_sof_dev *sdev, struct sof_ipc_dma_trace_posn *posn); void snd_sof_trace_notify_for_error(struct snd_sof_dev *sdev); From 6fbbc18ead0f4f64a722f7e325046e5860d2c52b Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 3 Jun 2019 11:20:25 -0500 Subject: [PATCH 131/626] ASoC: SOF: Do not send cmd via SHIM register We use shim registers only to notify the other side that a message was sent. The actual information for the message is transmitted via mailbox. cmd information inside shim register is not used by the DSP, so we remove it to avoid confusion. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 5 +---- sound/soc/sof/intel/cnl.c | 4 +--- sound/soc/sof/intel/hda-ipc.c | 4 +--- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 9e4c07eb889b..8765eedfcf54 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -373,13 +373,10 @@ static irqreturn_t byt_irq_thread(int irq, void *context) static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { - u64 cmd = msg->header; - /* send the message */ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size); - snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, - cmd | SHIM_BYT_IPCX_BUSY); + snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_BUSY); return 0; } diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index e59d180da7e2..fd86269b5037 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -151,13 +151,11 @@ static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev) static int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { - u32 cmd = msg->header; - /* send the message */ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size); snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR, - cmd | CNL_DSP_REG_HIPCIDR_BUSY); + CNL_DSP_REG_HIPCIDR_BUSY); return 0; } diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 51b285103394..728dd1e075a4 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -56,13 +56,11 @@ static void hda_dsp_ipc_dsp_done(struct snd_sof_dev *sdev) int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { - u32 cmd = msg->header; - /* send IPC message to DSP */ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size); snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI, - cmd | HDA_DSP_REG_HIPCI_BUSY); + HDA_DSP_REG_HIPCI_BUSY); return 0; } From c24b1b7279398c9140a8130b4c20db0c06d5dfc4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 3 Jun 2019 11:20:26 -0500 Subject: [PATCH 132/626] ASoC: SOF: Intel: cnl-ipc: read all IPC registers first Align with hardware recommended sequences, and read all IPC registers before doing any other actions. Playing with BUSY and DONE bits may invalidate values. The values read may not actually be necessary but at least this provides a snapshot of the IPC registers with no consistency issues. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index fd86269b5037..1fae75fc313f 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -42,6 +42,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA); hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL); hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR); + hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD); + hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR); /* reenable IPC interrupt */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, @@ -50,8 +52,6 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) /* reply message from DSP */ if (hipcida & CNL_DSP_REG_HIPCIDA_DONE && hipcctl & CNL_DSP_REG_HIPCCTL_DONE) { - hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, - CNL_DSP_REG_HIPCIDR); msg_ext = hipci & CNL_DSP_REG_HIPCIDR_MSG_MASK; msg = hipcida & CNL_DSP_REG_HIPCIDA_MSG_MASK; @@ -84,8 +84,6 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) /* new message from DSP */ if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) { - hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, - CNL_DSP_REG_HIPCTDD); msg = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK; msg_ext = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK; From ddbe9223393e4d067f010de65a05c9a6cb7790c1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 3 Jun 2019 11:20:27 -0500 Subject: [PATCH 133/626] ASoC: SOF: Intel: cnl-ipc: move code around for clarity Move all register access to cnl_ipc_host_done() No functionality change. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 1fae75fc313f..4ecba1d8ec7f 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -99,15 +99,6 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) snd_sof_ipc_msgs_rx(sdev); } - /* - * clear busy interrupt to tell dsp controller this - * interrupt has been accepted, not trigger it again - */ - snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, - CNL_DSP_REG_HIPCTDR, - CNL_DSP_REG_HIPCTDR_BUSY, - CNL_DSP_REG_HIPCTDR_BUSY); - cnl_ipc_host_done(sdev); ret = IRQ_HANDLED; @@ -118,6 +109,14 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) static void cnl_ipc_host_done(struct snd_sof_dev *sdev) { + /* + * clear busy interrupt to tell dsp controller this + * interrupt has been accepted, not trigger it again + */ + snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, + CNL_DSP_REG_HIPCTDR, + CNL_DSP_REG_HIPCTDR_BUSY, + CNL_DSP_REG_HIPCTDR_BUSY); /* * set done bit to ack dsp the msg has been * processed and send reply msg to dsp From 3f58521bc81455bdfec2a44febf25ace8988a47f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 3 Jun 2019 11:20:28 -0500 Subject: [PATCH 134/626] ASoC: SOF: Intel: cnl-ipc: re-enable IPC IRQ at end of handler Align with Skylake driver and enable the IRQ at end of handler, instead of at beginning. Also add an error log if we have nothing to do in this handler. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 4ecba1d8ec7f..b794a881542f 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -37,7 +37,7 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) u32 hipctdd; u32 msg; u32 msg_ext; - irqreturn_t ret = IRQ_NONE; + bool ipc_irq = false; hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA); hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL); @@ -45,10 +45,6 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD); hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR); - /* reenable IPC interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, - HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); - /* reply message from DSP */ if (hipcida & CNL_DSP_REG_HIPCIDA_DONE && hipcctl & CNL_DSP_REG_HIPCCTL_DONE) { @@ -79,7 +75,7 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) spin_unlock_irq(&sdev->ipc_lock); - ret = IRQ_HANDLED; + ipc_irq = true; } /* new message from DSP */ @@ -101,10 +97,22 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) cnl_ipc_host_done(sdev); - ret = IRQ_HANDLED; + ipc_irq = true; } - return ret; + if (!ipc_irq) { + /* + * This interrupt is not shared so no need to return IRQ_NONE. + */ + dev_err_ratelimited(sdev->dev, + "error: nothing to do in IRQ thread\n"); + } + + /* re-enable IPC interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, + HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); + + return IRQ_HANDLED; } static void cnl_ipc_host_done(struct snd_sof_dev *sdev) From 5dbeb8287421984a09c92a79c503f8bd41cf3fe7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 3 Jun 2019 11:20:29 -0500 Subject: [PATCH 135/626] ASoC: SOF: Intel: hda-ipc: read all IPC registers first Align with hardware recommended sequences, and read all IPC registers before doing any other actions. Playing with BUSY and DONE bits may invalidate values. The values read may not actually be necessary but at least this provides a snapshot of the IPC registers with no consistency issues. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ipc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 728dd1e075a4..1f01897fa6e3 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -145,6 +145,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) HDA_DSP_REG_HIPCIE); hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL); + hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI); + hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE); /* reenable IPC interrupt */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, @@ -153,8 +155,6 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) /* is this a reply message from the DSP */ if (hipcie & HDA_DSP_REG_HIPCIE_DONE && hipcctl & HDA_DSP_REG_HIPCCTL_DONE) { - hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, - HDA_DSP_REG_HIPCI); msg = hipci & HDA_DSP_REG_HIPCI_MSG_MASK; msg_ext = hipcie & HDA_DSP_REG_HIPCIE_MSG_MASK; @@ -202,9 +202,6 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) /* is this a new message from DSP */ if (hipct & HDA_DSP_REG_HIPCT_BUSY && hipcctl & HDA_DSP_REG_HIPCCTL_BUSY) { - - hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, - HDA_DSP_REG_HIPCTE); msg = hipct & HDA_DSP_REG_HIPCT_MSG_MASK; msg_ext = hipcte & HDA_DSP_REG_HIPCTE_MSG_MASK; From 66e65339b824a597a8c750ddf993af17c847dce6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 3 Jun 2019 11:20:30 -0500 Subject: [PATCH 136/626] ASoC: SOF: Intel: hda-ipc: re-enable IPC IRQ at end of handler Align with Skylake driver and enable the IRQ at end of handler, instead of at beginning. Also add an error log if we have nothing to do in this handler. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ipc.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 1f01897fa6e3..04972f27ffe6 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -131,7 +131,6 @@ static bool hda_dsp_ipc_is_sof(uint32_t msg) irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) { struct snd_sof_dev *sdev = context; - irqreturn_t ret = IRQ_NONE; u32 hipci; u32 hipcie; u32 hipct; @@ -139,6 +138,7 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) u32 hipcctl; u32 msg; u32 msg_ext; + bool ipc_irq = false; /* read IPC status */ hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, @@ -148,10 +148,6 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI); hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE); - /* reenable IPC interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, - HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); - /* is this a reply message from the DSP */ if (hipcie & HDA_DSP_REG_HIPCIE_DONE && hipcctl & HDA_DSP_REG_HIPCCTL_DONE) { @@ -196,7 +192,7 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) spin_unlock_irq(&sdev->ipc_lock); - ret = IRQ_HANDLED; + ipc_irq = true; } /* is this a new message from DSP */ @@ -225,10 +221,22 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) hda_dsp_ipc_host_done(sdev); - ret = IRQ_HANDLED; + ipc_irq = true; } - return ret; + if (!ipc_irq) { + /* + * This interrupt is not shared so no need to return IRQ_NONE. + */ + dev_err_ratelimited(sdev->dev, + "error: nothing to do in IRQ thread\n"); + } + + /* re-enable IPC interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, + HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); + + return IRQ_HANDLED; } /* is this IRQ for ADSP ? - we only care about IPC here */ From 09a173a63fbb89762712a4ec48722ba98d4e1bcc Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 3 Jun 2019 11:20:31 -0500 Subject: [PATCH 137/626] ASoC: SOF: Intel: ipc: don't check for HIPCCTL register value The HIPCCTL register controls the IPC interrupts. It can be set or cleared to mask or enable these interrupts, but it makes no sense to read and test its fields in an interrupt (which can only executed if its fields are set). Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 5 +---- sound/soc/sof/intel/hda-ipc.c | 8 ++------ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index b794a881542f..9a4927b6b6ae 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -31,7 +31,6 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) { struct snd_sof_dev *sdev = context; u32 hipci; - u32 hipcctl; u32 hipcida; u32 hipctdr; u32 hipctdd; @@ -40,14 +39,12 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) bool ipc_irq = false; hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA); - hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL); hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR); hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD); hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR); /* reply message from DSP */ - if (hipcida & CNL_DSP_REG_HIPCIDA_DONE && - hipcctl & CNL_DSP_REG_HIPCCTL_DONE) { + if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) { msg_ext = hipci & CNL_DSP_REG_HIPCIDR_MSG_MASK; msg = hipcida & CNL_DSP_REG_HIPCIDA_MSG_MASK; diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 04972f27ffe6..50244b82600c 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -135,7 +135,6 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) u32 hipcie; u32 hipct; u32 hipcte; - u32 hipcctl; u32 msg; u32 msg_ext; bool ipc_irq = false; @@ -144,13 +143,11 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE); hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); - hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL); hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI); hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE); /* is this a reply message from the DSP */ - if (hipcie & HDA_DSP_REG_HIPCIE_DONE && - hipcctl & HDA_DSP_REG_HIPCCTL_DONE) { + if (hipcie & HDA_DSP_REG_HIPCIE_DONE) { msg = hipci & HDA_DSP_REG_HIPCI_MSG_MASK; msg_ext = hipcie & HDA_DSP_REG_HIPCIE_MSG_MASK; @@ -196,8 +193,7 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) } /* is this a new message from DSP */ - if (hipct & HDA_DSP_REG_HIPCT_BUSY && - hipcctl & HDA_DSP_REG_HIPCCTL_BUSY) { + if (hipct & HDA_DSP_REG_HIPCT_BUSY) { msg = hipct & HDA_DSP_REG_HIPCT_MSG_MASK; msg_ext = hipcte & HDA_DSP_REG_HIPCTE_MSG_MASK; From a893ef9b8bba6a1ba262d9afa04012fcab334c34 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Mon, 3 Jun 2019 11:18:14 -0500 Subject: [PATCH 138/626] ASoC: SOF: soundwire: add initial soundwire support Add soundwire dai type and update ABI version. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/sof/dai.h | 1 + include/uapi/sound/sof/abi.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h index 3b67c93ff101..3d174e20aa53 100644 --- a/include/sound/sof/dai.h +++ b/include/sound/sof/dai.h @@ -49,6 +49,7 @@ enum sof_ipc_dai_type { SOF_DAI_INTEL_SSP, /**< Intel SSP */ SOF_DAI_INTEL_DMIC, /**< Intel DMIC */ SOF_DAI_INTEL_HDA, /**< Intel HD/A */ + SOF_DAI_INTEL_SOUNDWIRE, /**< Intel SoundWire */ }; /* general purpose DAI configuration */ diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 37e0a90dc9e6..13a4eca04577 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 4 +#define SOF_ABI_MINOR 5 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ From 663580695611b9c3837cdf596de2194234f0fbd5 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Mon, 3 Jun 2019 11:18:21 -0500 Subject: [PATCH 139/626] ASoC: SOF: topology: add support for mux/demux component Add enumerations to support mux/demux processing component. Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 3 +++ sound/soc/sof/topology.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 46b2a7e63167..4978999fd362 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -35,6 +35,7 @@ enum sof_comp_type { SOF_COMP_KEYWORD_DETECT, SOF_COMP_KPB, /* A key phrase buffer component */ SOF_COMP_SELECTOR, /**< channel selector component */ + SOF_COMP_DEMUX, /* keep FILEREAD/FILEWRITE as the last ones */ SOF_COMP_FILEREAD = 10000, /**< host test based file IO */ SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */ @@ -175,6 +176,8 @@ enum sof_ipc_process_type { SOF_PROCESS_KEYWORD_DETECT, /**< Keyword Detection */ SOF_PROCESS_KPB, /**< KeyPhrase Buffer Manager */ SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */ + SOF_PROCESS_MUX, + SOF_PROCESS_DEMUX, }; /* generic "effect", "codec" or proprietary processing component */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 745cb875863c..b969686f954f 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -394,6 +394,8 @@ static const struct sof_process_types sof_process[] = { {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT}, {"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB}, {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR}, + {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, + {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, }; static enum sof_ipc_process_type find_process(const char *name) From e3adc9495ab26fc4bfe29253d4e7aad47dab2307 Mon Sep 17 00:00:00 2001 From: Bard liao Date: Mon, 3 Jun 2019 11:18:17 -0500 Subject: [PATCH 140/626] ASoC: SOF: send time stamp to FW for alignment Timer will be reset when DSP is powered down. So the time stamp of trace log will be reset after resume. Send time stamp to FW can align the time stamp and avoid reset time stamp in trace log. Signed-off-by: Bard liao Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/sof/header.h | 1 + include/sound/sof/trace.h | 10 ++++++++++ include/uapi/sound/sof/abi.h | 2 +- sound/soc/sof/trace.c | 16 +++++++++++++--- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index 1efcf7b18ec2..ab5862d80afe 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -102,6 +102,7 @@ /* trace and debug */ #define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001) #define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002) +#define SOF_IPC_TRACE_DMA_PARAMS_EXT SOF_CMD_TYPE(0x003) /* Get message component id */ #define SOF_IPC_MESSAGE_ID(x) ((x) & 0xffff) diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h index 7d211f319a92..2187ff7d07ce 100644 --- a/include/sound/sof/trace.h +++ b/include/sound/sof/trace.h @@ -19,12 +19,22 @@ #define SOF_TRACE_FILENAME_SIZE 32 /* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS */ +/* Deprecated - use sof_ipc_dma_trace_params_ext */ struct sof_ipc_dma_trace_params { struct sof_ipc_cmd_hdr hdr; struct sof_ipc_host_buffer buffer; uint32_t stream_tag; } __packed; +/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS_EXT */ +struct sof_ipc_dma_trace_params_ext { + struct sof_ipc_cmd_hdr hdr; + struct sof_ipc_host_buffer buffer; + uint32_t stream_tag; + uint64_t timestamp_ns; /* in nanosecond */ + uint32_t reserved[8]; +} __packed; + /* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS */ struct sof_ipc_dma_trace_posn { struct sof_ipc_reply rhdr; diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 0868eb47acf7..92eee681bc62 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 6 +#define SOF_ABI_MINOR 7 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index b02520f8e595..befed975161c 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -161,7 +161,9 @@ static int trace_debugfs_create(struct snd_sof_dev *sdev) int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev) { - struct sof_ipc_dma_trace_params params; + struct sof_ipc_fw_ready *ready = &sdev->fw_ready; + struct sof_ipc_fw_version *v = &ready->version; + struct sof_ipc_dma_trace_params_ext params; struct sof_ipc_reply ipc_reply; int ret; @@ -169,8 +171,16 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev) return -EINVAL; /* set IPC parameters */ - params.hdr.size = sizeof(params); - params.hdr.cmd = SOF_IPC_GLB_TRACE_MSG | SOF_IPC_TRACE_DMA_PARAMS; + params.hdr.cmd = SOF_IPC_GLB_TRACE_MSG; + /* PARAMS_EXT is only supported from ABI 3.7.0 onwards */ + if (v->abi_version >= SOF_ABI_VER(3, 7, 0)) { + params.hdr.size = sizeof(struct sof_ipc_dma_trace_params_ext); + params.hdr.cmd |= SOF_IPC_TRACE_DMA_PARAMS_EXT; + params.timestamp_ns = ktime_get(); /* in nanosecond */ + } else { + params.hdr.size = sizeof(struct sof_ipc_dma_trace_params); + params.hdr.cmd |= SOF_IPC_TRACE_DMA_PARAMS; + } params.buffer.phy_addr = sdev->dmatp.addr; params.buffer.size = sdev->dmatb.bytes; params.buffer.pages = sdev->dma_trace_pages; From 53b22d25ec36cebc2f5888a0bd5fba84b05f3dee Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 3 Jun 2019 11:18:19 -0500 Subject: [PATCH 141/626] ASoC: SOF: ipc: Introduce SOF_IPC_GLB_TEST_MSG IPC command Add a new class of IPC command along with the first test type, IPC_FLOOD, which will be used for flooding the DSP with IPCs. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/sof/header.h | 6 +++++- sound/soc/sof/ipc.c | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index ab5862d80afe..12867bbd4372 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -49,6 +49,7 @@ #define SOF_IPC_GLB_DAI_MSG SOF_GLB_TYPE(0x8U) #define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U) #define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU) +#define SOF_IPC_GLB_TEST_MSG SOF_GLB_TYPE(0xBU) /* * DSP Command Message Types @@ -99,11 +100,14 @@ #define SOF_IPC_STREAM_VORBIS_PARAMS SOF_CMD_TYPE(0x010) #define SOF_IPC_STREAM_VORBIS_FREE SOF_CMD_TYPE(0x011) -/* trace and debug */ +/* trace */ #define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001) #define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002) #define SOF_IPC_TRACE_DMA_PARAMS_EXT SOF_CMD_TYPE(0x003) +/* debug */ +#define SOF_IPC_TEST_IPC_FLOOD SOF_CMD_TYPE(0x001) + /* Get message component id */ #define SOF_IPC_MESSAGE_ID(x) ((x) & 0xffff) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 2414640a32d1..558b596e2133 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -175,6 +175,15 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd) break; case SOF_IPC_GLB_TRACE_MSG: str = "GLB_TRACE_MSG"; break; + case SOF_IPC_GLB_TEST_MSG: + str = "GLB_TEST_MSG"; + switch (type) { + case SOF_IPC_TEST_IPC_FLOOD: + str2 = "IPC_FLOOD"; break; + default: + str2 = "unknown type"; break; + } + break; default: str = "unknown GLB command"; break; } From 091c12e1f50cce93b1af90e56cad88787ec86dfb Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 3 Jun 2019 11:18:20 -0500 Subject: [PATCH 142/626] ASoC: SOF: debug: add new debugfs entries for IPC flood test Add a couple of new debugfs entries "ipc_flood_count" and "ipc_flood_duration_ms" that can be used to execute the IPC flood test. "ipc_flood_count" floods the DSP with the number of test IPCs specified and ipc_flood_duration_ms floods the DSP with test IPC's for the duration(in ms) specified. The test stats such as average, min and max IPC response times are logged in the dmesg and saved in the debugfs entry cache buffer. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 8 ++ sound/soc/sof/debug.c | 243 +++++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-priv.h | 6 +- 3 files changed, 256 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index ca3ad3362478..1d4b4dced4b6 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -131,6 +131,14 @@ config SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE Say Y if you want to enable caching the memory windows. If unsure, select "N". +config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST + bool "SOF enable IPC flood test" + help + This option enables the IPC flood test which can be used to flood + the DSP with test IPCs and gather stats about response times. + Say Y if you want to enable IPC flood test. + If unsure, select "N". + endif ## SND_SOC_SOF_DEBUG endif ## SND_SOC_SOF_OPTIONS diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 219c3becf670..54bb53bfc81b 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -17,6 +17,203 @@ #include "sof-priv.h" #include "ops.h" +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) +#define MAX_IPC_FLOOD_DURATION_MS 1000 +#define MAX_IPC_FLOOD_COUNT 10000 +#define IPC_FLOOD_TEST_RESULT_LEN 512 + +static int sof_debug_ipc_flood_test(struct snd_sof_dev *sdev, + struct snd_sof_dfsentry *dfse, + bool flood_duration_test, + unsigned long ipc_duration_ms, + unsigned long ipc_count) +{ + struct sof_ipc_cmd_hdr hdr; + struct sof_ipc_reply reply; + u64 min_response_time = U64_MAX; + ktime_t start, end, test_end; + u64 avg_response_time = 0; + u64 max_response_time = 0; + u64 ipc_response_time; + int i = 0; + int ret; + + /* configure test IPC */ + hdr.cmd = SOF_IPC_GLB_TEST_MSG | SOF_IPC_TEST_IPC_FLOOD; + hdr.size = sizeof(hdr); + + /* set test end time for duration flood test */ + if (flood_duration_test) + test_end = ktime_get_ns() + ipc_duration_ms * NSEC_PER_MSEC; + + /* send test IPC's */ + while (1) { + start = ktime_get(); + ret = sof_ipc_tx_message(sdev->ipc, hdr.cmd, &hdr, hdr.size, + &reply, sizeof(reply)); + end = ktime_get(); + + if (ret < 0) + break; + + /* compute min and max response times */ + ipc_response_time = ktime_to_ns(ktime_sub(end, start)); + min_response_time = min(min_response_time, ipc_response_time); + max_response_time = max(max_response_time, ipc_response_time); + + /* sum up response times */ + avg_response_time += ipc_response_time; + i++; + + /* test complete? */ + if (flood_duration_test) { + if (ktime_to_ns(end) >= test_end) + break; + } else { + if (i == ipc_count) + break; + } + } + + if (ret < 0) + dev_err(sdev->dev, + "error: ipc flood test failed at %d iterations\n", i); + + /* return if the first IPC fails */ + if (!i) + return ret; + + /* compute average response time */ + do_div(avg_response_time, i); + + /* clear previous test output */ + memset(dfse->cache_buf, 0, IPC_FLOOD_TEST_RESULT_LEN); + + if (flood_duration_test) { + dev_dbg(sdev->dev, "IPC Flood test duration: %lums\n", + ipc_duration_ms); + snprintf(dfse->cache_buf, IPC_FLOOD_TEST_RESULT_LEN, + "IPC Flood test duration: %lums\n", ipc_duration_ms); + } + + dev_dbg(sdev->dev, + "IPC Flood count: %d, Avg response time: %lluns\n", + i, avg_response_time); + dev_dbg(sdev->dev, "Max response time: %lluns\n", + max_response_time); + dev_dbg(sdev->dev, "Min response time: %lluns\n", + min_response_time); + + /* format output string */ + snprintf(dfse->cache_buf + strlen(dfse->cache_buf), + IPC_FLOOD_TEST_RESULT_LEN - strlen(dfse->cache_buf), + "IPC Flood count: %d\nAvg response time: %lluns\n", + i, avg_response_time); + + snprintf(dfse->cache_buf + strlen(dfse->cache_buf), + IPC_FLOOD_TEST_RESULT_LEN - strlen(dfse->cache_buf), + "Max response time: %lluns\nMin response time: %lluns\n", + max_response_time, min_response_time); + + return ret; +} +#endif + +static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) + struct snd_sof_dfsentry *dfse = file->private_data; + struct snd_sof_dev *sdev = dfse->sdev; + unsigned long ipc_duration_ms = 0; + bool flood_duration_test = false; + unsigned long ipc_count = 0; + int err; +#endif + size_t size; + char *string; + int ret; + + string = kzalloc(count, GFP_KERNEL); + if (!string) + return -ENOMEM; + + size = simple_write_to_buffer(string, count, ppos, buffer, count); + ret = size; + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) + /* + * write op is only supported for ipc_flood_count or + * ipc_flood_duration_ms debugfs entries atm. + * ipc_flood_count floods the DSP with the number of IPC's specified. + * ipc_duration_ms test floods the DSP for the time specified + * in the debugfs entry. + */ + if (strcmp(dfse->dfsentry->d_name.name, "ipc_flood_count") && + strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) + return -EINVAL; + + if (!strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) + flood_duration_test = true; + + /* test completion criterion */ + if (flood_duration_test) + ret = kstrtoul(string, 0, &ipc_duration_ms); + else + ret = kstrtoul(string, 0, &ipc_count); + if (ret < 0) + return ret; + + /* limit max duration/ipc count for flood test */ + if (flood_duration_test) { + if (!ipc_duration_ms) { + ret = size; + goto out; + } + + /* find the minimum. min() is not used to avoid warnings */ + if (ipc_duration_ms > MAX_IPC_FLOOD_DURATION_MS) + ipc_duration_ms = MAX_IPC_FLOOD_DURATION_MS; + } else { + if (!ipc_count) { + ret = size; + goto out; + } + + /* find the minimum. min() is not used to avoid warnings */ + if (ipc_count > MAX_IPC_FLOOD_COUNT) + ipc_count = MAX_IPC_FLOOD_COUNT; + } + + ret = pm_runtime_get_sync(sdev->dev); + if (ret < 0) { + dev_err_ratelimited(sdev->dev, + "error: debugfs write failed to resume %d\n", + ret); + pm_runtime_put_noidle(sdev->dev); + return ret; + } + + /* flood test */ + ret = sof_debug_ipc_flood_test(sdev, dfse, flood_duration_test, + ipc_duration_ms, ipc_count); + + pm_runtime_mark_last_busy(sdev->dev); + err = pm_runtime_put_autosuspend(sdev->dev); + if (err < 0) + dev_err_ratelimited(sdev->dev, + "error: debugfs write failed to idle %d\n", + err); + + /* return size if test is successful */ + if (ret >= 0) + ret = size; +out: +#endif + kfree(string); + return ret; +} + static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { @@ -28,6 +225,22 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, int size; u8 *buf; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) + if ((!strcmp(dfse->dfsentry->d_name.name, "ipc_flood_count") || + !strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) && + dfse->cache_buf) { + if (*ppos) + return 0; + + count = strlen(dfse->cache_buf); + size_ret = copy_to_user(buffer, dfse->cache_buf, count); + if (size_ret) + return -EFAULT; + + *ppos += count; + return count; + } +#endif size = dfse->size; /* validate position & count */ @@ -107,6 +320,7 @@ static const struct file_operations sof_dfs_fops = { .open = simple_open, .read = sof_dfsentry_read, .llseek = default_llseek, + .write = sof_dfsentry_write, }; /* create FS entry for debug files that can expose DSP memories, registers */ @@ -177,6 +391,17 @@ int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev, dfse->size = size; dfse->sdev = sdev; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) + /* + * cache_buf is unused for SOF_DFSENTRY_TYPE_BUF debugfs entries. + * So, use it to save the results of the last IPC flood test. + */ + dfse->cache_buf = devm_kzalloc(sdev->dev, IPC_FLOOD_TEST_RESULT_LEN, + GFP_KERNEL); + if (!dfse->cache_buf) + return -ENOMEM; +#endif + dfse->dfsentry = debugfs_create_file(name, mode, sdev->debugfs_root, dfse, &sof_dfs_fops); if (!dfse->dfsentry) { @@ -221,6 +446,24 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) return err; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) + /* create read-write ipc_flood_count debugfs entry */ + err = snd_sof_debugfs_buf_item(sdev, NULL, 0, + "ipc_flood_count", 0666); + + /* errors are only due to memory allocation, not debugfs */ + if (err < 0) + return err; + + /* create read-write ipc_flood_duration_ms debugfs entry */ + err = snd_sof_debugfs_buf_item(sdev, NULL, 0, + "ipc_flood_duration_ms", 0666); + + /* errors are only due to memory allocation, not debugfs */ + if (err < 0) + return err; +#endif + return 0; } EXPORT_SYMBOL_GPL(snd_sof_dbg_init); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index ce22240cd93a..17f3d2a5a701 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -56,6 +56,10 @@ #define SOF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_FLOAT) +#define ENABLE_DEBUGFS_CACHEBUF \ + (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) || \ + IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)) + struct snd_sof_dev; struct snd_sof_ipc_msg; struct snd_sof_ipc; @@ -226,7 +230,7 @@ struct snd_sof_dfsentry { * or if it is accessible only when the DSP is in D0. */ enum sof_debugfs_access_type access_type; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) +#if ENABLE_DEBUGFS_CACHEBUF char *cache_buf; /* buffer to cache the contents of debugfs memory */ #endif struct snd_sof_dev *sdev; From d6e65bb7ff0d360c4c5462c3d0b237f2a07e5312 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 28 May 2019 12:30:17 +0800 Subject: [PATCH 143/626] ASoC: rt1011: Add RT1011 amplifier driver This is the initial amplifier driver for rt1011. Signed-off-by: Shuming Fan Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/rt1011.txt | 32 + sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt1011.c | 2241 +++++++++++++++++ sound/soc/codecs/rt1011.h | 672 +++++ 5 files changed, 2953 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/rt1011.txt create mode 100644 sound/soc/codecs/rt1011.c create mode 100644 sound/soc/codecs/rt1011.h diff --git a/Documentation/devicetree/bindings/sound/rt1011.txt b/Documentation/devicetree/bindings/sound/rt1011.txt new file mode 100644 index 000000000000..35a23e60d679 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt1011.txt @@ -0,0 +1,32 @@ +RT1011 Mono Class D Audio Amplifier + +This device supports I2C only. + +Required properties: + +- compatible : "realtek,rt1011". + +- reg : The I2C address of the device. This I2C address decide by + two input pins (ASEL1 and ASEL2). + ------------------------------------- + | ASEL2 | ASEL1 | Address | + ------------------------------------- + | 0 | 0 | 0x38 | + ------------------------------------- + | 0 | 1 | 0x39 | + ------------------------------------- + | 1 | 0 | 0x3a | + ------------------------------------- + | 1 | 1 | 0x3b | + ------------------------------------- + +Pins on the device (for linking into audio routes) for RT1011: + + * SPO + +Example: + +rt1011: codec@38 { + compatible = "realtek,rt1011"; + reg = <0x38>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0835d4b0d8c3..1bda52ef0cd0 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -140,6 +140,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT274 if I2C select SND_SOC_RT286 if I2C select SND_SOC_RT298 if I2C + select SND_SOC_RT1011 if I2C select SND_SOC_RT1305 if I2C select SND_SOC_RT5514 if I2C select SND_SOC_RT5616 if I2C @@ -877,6 +878,7 @@ config SND_SOC_RL6231 default y if SND_SOC_RT5670=y default y if SND_SOC_RT5677=y default y if SND_SOC_RT5682=y + default y if SND_SOC_RT1011=y default y if SND_SOC_RT1305=y default m if SND_SOC_RT5514=m default m if SND_SOC_RT5616=m @@ -891,6 +893,7 @@ config SND_SOC_RL6231 default m if SND_SOC_RT5670=m default m if SND_SOC_RT5677=m default m if SND_SOC_RT5682=m + default m if SND_SOC_RT1011=m default m if SND_SOC_RT1305=m config SND_SOC_RL6347A @@ -914,6 +917,9 @@ config SND_SOC_RT298 tristate depends on I2C +config SND_SOC_RT1011 + tristate + config SND_SOC_RT1305 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 454b8087a5bd..112701fd44a8 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -142,6 +142,7 @@ snd-soc-pcm512x-spi-objs := pcm512x-spi.o snd-soc-rk3328-objs := rk3328_codec.o snd-soc-rl6231-objs := rl6231.o snd-soc-rl6347a-objs := rl6347a.o +snd-soc-rt1011-objs := rt1011.o snd-soc-rt1305-objs := rt1305.o snd-soc-rt274-objs := rt274.o snd-soc-rt286-objs := rt286.o @@ -417,6 +418,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o +obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o obj-$(CONFIG_SND_SOC_RT274) += snd-soc-rt274.o obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c new file mode 100644 index 000000000000..349d6db7ecd4 --- /dev/null +++ b/sound/soc/codecs/rt1011.c @@ -0,0 +1,2241 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * rt1011.c -- rt1011 ALSA SoC amplifier component driver + * + * Copyright(c) 2019 Realtek Semiconductor Corp. + * + * Author: Shuming Fan + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rl6231.h" +#include "rt1011.h" + +static int rt1011_calibrate(struct rt1011_priv *rt1011, + unsigned char cali_flag); + +static const struct reg_sequence init_list[] = { + + { RT1011_POWER_9, 0xa840 }, + + { RT1011_ADC_SET_5, 0x0a20 }, + { RT1011_DAC_SET_2, 0xa232 }, + { RT1011_ADC_SET_1, 0x2925 }, + + { RT1011_SPK_PRO_DC_DET_1, 0xb00c }, + { RT1011_SPK_PRO_DC_DET_2, 0xcccc }, + + { RT1011_A_TIMING_1, 0x6054 }, + + { RT1011_POWER_7, 0x3e55 }, + { RT1011_POWER_8, 0x0520 }, + { RT1011_BOOST_CON_1, 0xe188 }, + { RT1011_POWER_4, 0x16f2 }, + + { RT1011_CROSS_BQ_SET_1, 0x0004 }, + { RT1011_SIL_DET, 0xc313 }, + { RT1011_SINE_GEN_REG_1, 0x0707 }, + + { RT1011_DC_CALIB_CLASSD_3, 0xcb00 }, + + { RT1011_DAC_SET_1, 0xe702 }, + { RT1011_DAC_SET_3, 0x2004 }, +}; +#define RT1011_INIT_REG_LEN ARRAY_SIZE(init_list) + +static const struct reg_default rt1011_reg[] = { + {0x0000, 0x0000}, + {0x0002, 0x0000}, + {0x0004, 0xa000}, + {0x0006, 0x0000}, + {0x0008, 0x0003}, + {0x000a, 0x087e}, + {0x000c, 0x0020}, + {0x000e, 0x9002}, + {0x0010, 0x0000}, + {0x0012, 0x0000}, + {0x0020, 0x0c40}, + {0x0022, 0x4313}, + {0x0076, 0x0000}, + {0x0078, 0x0000}, + {0x007a, 0x0000}, + {0x007c, 0x10ec}, + {0x007d, 0x1011}, + {0x00f0, 0x5000}, + {0x00f2, 0x0374}, + {0x00f3, 0x0000}, + {0x00f4, 0x0000}, + {0x0100, 0x0038}, + {0x0102, 0xff02}, + {0x0104, 0x0232}, + {0x0106, 0x200c}, + {0x0107, 0x0000}, + {0x0108, 0x2f2f}, + {0x010a, 0x2f2f}, + {0x010c, 0x002f}, + {0x010e, 0xe000}, + {0x0110, 0x0820}, + {0x0111, 0x4010}, + {0x0112, 0x0000}, + {0x0114, 0x0000}, + {0x0116, 0x0000}, + {0x0118, 0x0000}, + {0x011a, 0x0101}, + {0x011c, 0x4567}, + {0x011e, 0x0000}, + {0x0120, 0x0000}, + {0x0122, 0x0000}, + {0x0124, 0x0123}, + {0x0126, 0x4567}, + {0x0200, 0x0000}, + {0x0300, 0xffdd}, + {0x0302, 0x001e}, + {0x0311, 0x0000}, + {0x0313, 0x5254}, + {0x0314, 0x0062}, + {0x0316, 0x7f40}, + {0x0319, 0x000f}, + {0x031a, 0xffff}, + {0x031b, 0x0000}, + {0x031c, 0x009f}, + {0x031d, 0xffff}, + {0x031e, 0x0000}, + {0x031f, 0x0000}, + {0x0320, 0xe31c}, + {0x0321, 0x0000}, + {0x0322, 0x0000}, + {0x0324, 0x0000}, + {0x0326, 0x0002}, + {0x0328, 0x20b2}, + {0x0329, 0x0175}, + {0x032a, 0x32ad}, + {0x032b, 0x3455}, + {0x032c, 0x0528}, + {0x032d, 0xa800}, + {0x032e, 0x030e}, + {0x0330, 0x2080}, + {0x0332, 0x0034}, + {0x0334, 0x0000}, + {0x0508, 0x0010}, + {0x050a, 0x0018}, + {0x050c, 0x0000}, + {0x050d, 0xffff}, + {0x050e, 0x1f1f}, + {0x050f, 0x04ff}, + {0x0510, 0x4020}, + {0x0511, 0x01f0}, + {0x0512, 0x0702}, + {0x0516, 0xbb80}, + {0x0517, 0xffff}, + {0x0518, 0xffff}, + {0x0519, 0x307f}, + {0x051a, 0xffff}, + {0x051b, 0x0000}, + {0x051c, 0x0000}, + {0x051d, 0x2000}, + {0x051e, 0x0000}, + {0x051f, 0x0000}, + {0x0520, 0x0000}, + {0x0521, 0x1001}, + {0x0522, 0x7fff}, + {0x0524, 0x7fff}, + {0x0526, 0x0000}, + {0x0528, 0x0000}, + {0x052a, 0x0000}, + {0x0530, 0x0401}, + {0x0532, 0x3000}, + {0x0534, 0x0000}, + {0x0535, 0xffff}, + {0x0536, 0x101c}, + {0x0538, 0x1814}, + {0x053a, 0x100c}, + {0x053c, 0x0804}, + {0x053d, 0x0000}, + {0x053e, 0x0000}, + {0x053f, 0x0000}, + {0x0540, 0x0000}, + {0x0541, 0x0000}, + {0x0542, 0x0000}, + {0x0543, 0x0000}, + {0x0544, 0x001c}, + {0x0545, 0x1814}, + {0x0546, 0x100c}, + {0x0547, 0x0804}, + {0x0548, 0x0000}, + {0x0549, 0x0000}, + {0x054a, 0x0000}, + {0x054b, 0x0000}, + {0x054c, 0x0000}, + {0x054d, 0x0000}, + {0x054e, 0x0000}, + {0x054f, 0x0000}, + {0x0566, 0x0000}, + {0x0568, 0x20f1}, + {0x056a, 0x0007}, + {0x0600, 0x9d00}, + {0x0611, 0x2000}, + {0x0612, 0x505f}, + {0x0613, 0x0444}, + {0x0614, 0x4000}, + {0x0615, 0x4004}, + {0x0616, 0x0606}, + {0x0617, 0x8904}, + {0x0618, 0xe021}, + {0x0621, 0x2000}, + {0x0622, 0x505f}, + {0x0623, 0x0444}, + {0x0624, 0x4000}, + {0x0625, 0x4004}, + {0x0626, 0x0606}, + {0x0627, 0x8704}, + {0x0628, 0xe021}, + {0x0631, 0x2000}, + {0x0632, 0x517f}, + {0x0633, 0x0440}, + {0x0634, 0x4000}, + {0x0635, 0x4104}, + {0x0636, 0x0306}, + {0x0637, 0x8904}, + {0x0638, 0xe021}, + {0x0702, 0x0014}, + {0x0704, 0x0000}, + {0x0706, 0x0014}, + {0x0708, 0x0000}, + {0x070a, 0x0000}, + {0x0710, 0x0200}, + {0x0711, 0x0000}, + {0x0712, 0x0200}, + {0x0713, 0x0000}, + {0x0720, 0x0200}, + {0x0721, 0x0000}, + {0x0722, 0x0000}, + {0x0723, 0x0000}, + {0x0724, 0x0000}, + {0x0725, 0x0000}, + {0x0726, 0x0000}, + {0x0727, 0x0000}, + {0x0728, 0x0000}, + {0x0729, 0x0000}, + {0x0730, 0x0200}, + {0x0731, 0x0000}, + {0x0732, 0x0000}, + {0x0733, 0x0000}, + {0x0734, 0x0000}, + {0x0735, 0x0000}, + {0x0736, 0x0000}, + {0x0737, 0x0000}, + {0x0738, 0x0000}, + {0x0739, 0x0000}, + {0x0740, 0x0200}, + {0x0741, 0x0000}, + {0x0742, 0x0000}, + {0x0743, 0x0000}, + {0x0744, 0x0000}, + {0x0745, 0x0000}, + {0x0746, 0x0000}, + {0x0747, 0x0000}, + {0x0748, 0x0000}, + {0x0749, 0x0000}, + {0x0750, 0x0200}, + {0x0751, 0x0000}, + {0x0752, 0x0000}, + {0x0753, 0x0000}, + {0x0754, 0x0000}, + {0x0755, 0x0000}, + {0x0756, 0x0000}, + {0x0757, 0x0000}, + {0x0758, 0x0000}, + {0x0759, 0x0000}, + {0x0760, 0x0200}, + {0x0761, 0x0000}, + {0x0762, 0x0000}, + {0x0763, 0x0000}, + {0x0764, 0x0000}, + {0x0765, 0x0000}, + {0x0766, 0x0000}, + {0x0767, 0x0000}, + {0x0768, 0x0000}, + {0x0769, 0x0000}, + {0x0770, 0x0200}, + {0x0771, 0x0000}, + {0x0772, 0x0000}, + {0x0773, 0x0000}, + {0x0774, 0x0000}, + {0x0775, 0x0000}, + {0x0776, 0x0000}, + {0x0777, 0x0000}, + {0x0778, 0x0000}, + {0x0779, 0x0000}, + {0x0780, 0x0200}, + {0x0781, 0x0000}, + {0x0782, 0x0000}, + {0x0783, 0x0000}, + {0x0784, 0x0000}, + {0x0785, 0x0000}, + {0x0786, 0x0000}, + {0x0787, 0x0000}, + {0x0788, 0x0000}, + {0x0789, 0x0000}, + {0x0790, 0x0200}, + {0x0791, 0x0000}, + {0x0792, 0x0000}, + {0x0793, 0x0000}, + {0x0794, 0x0000}, + {0x0795, 0x0000}, + {0x0796, 0x0000}, + {0x0797, 0x0000}, + {0x0798, 0x0000}, + {0x0799, 0x0000}, + {0x07a0, 0x0200}, + {0x07a1, 0x0000}, + {0x07a2, 0x0000}, + {0x07a3, 0x0000}, + {0x07a4, 0x0000}, + {0x07a5, 0x0000}, + {0x07a6, 0x0000}, + {0x07a7, 0x0000}, + {0x07a8, 0x0000}, + {0x07a9, 0x0000}, + {0x07b0, 0x0200}, + {0x07b1, 0x0000}, + {0x07b2, 0x0000}, + {0x07b3, 0x0000}, + {0x07b4, 0x0000}, + {0x07b5, 0x0000}, + {0x07b6, 0x0000}, + {0x07b7, 0x0000}, + {0x07b8, 0x0000}, + {0x07b9, 0x0000}, + {0x07c0, 0x0200}, + {0x07c1, 0x0000}, + {0x07c2, 0x0000}, + {0x07c3, 0x0000}, + {0x07c4, 0x0000}, + {0x07c5, 0x0000}, + {0x07c6, 0x0000}, + {0x07c7, 0x0000}, + {0x07c8, 0x0000}, + {0x07c9, 0x0000}, + {0x1000, 0x4040}, + {0x1002, 0x6505}, + {0x1004, 0x5405}, + {0x1006, 0x5555}, + {0x1007, 0x003f}, + {0x1008, 0x7fd7}, + {0x1009, 0x770f}, + {0x100a, 0xfffe}, + {0x100b, 0xe000}, + {0x100c, 0x0000}, + {0x100d, 0x0007}, + {0x1010, 0xa433}, + {0x1020, 0x0000}, + {0x1022, 0x0000}, + {0x1024, 0x0000}, + {0x1200, 0x5a01}, + {0x1202, 0x6324}, + {0x1204, 0x0b00}, + {0x1206, 0x0000}, + {0x1208, 0x0000}, + {0x120a, 0x0024}, + {0x120c, 0x0000}, + {0x120e, 0x000e}, + {0x1210, 0x0000}, + {0x1212, 0x0000}, + {0x1300, 0x0701}, + {0x1302, 0x12f9}, + {0x1304, 0x3405}, + {0x1305, 0x0844}, + {0x1306, 0x5611}, + {0x1308, 0x555e}, + {0x130a, 0xa605}, + {0x130c, 0x2000}, + {0x130e, 0x0000}, + {0x130f, 0x0001}, + {0x1310, 0xaa48}, + {0x1312, 0x0285}, + {0x1314, 0xaaaa}, + {0x1316, 0xaaa0}, + {0x1318, 0x2aaa}, + {0x131a, 0xaa07}, + {0x1322, 0x0029}, + {0x1323, 0x4a52}, + {0x1324, 0x002c}, + {0x1325, 0x0b02}, + {0x1326, 0x002d}, + {0x1327, 0x6b5a}, + {0x1328, 0x002e}, + {0x1329, 0xcbb2}, + {0x132a, 0x0030}, + {0x132b, 0x2c0b}, + {0x1330, 0x0031}, + {0x1331, 0x8c63}, + {0x1332, 0x0032}, + {0x1333, 0xecbb}, + {0x1334, 0x0034}, + {0x1335, 0x4d13}, + {0x1336, 0x0037}, + {0x1337, 0x0dc3}, + {0x1338, 0x003d}, + {0x1339, 0xef7b}, + {0x133a, 0x0044}, + {0x133b, 0xd134}, + {0x133c, 0x0047}, + {0x133d, 0x91e4}, + {0x133e, 0x004d}, + {0x133f, 0xc370}, + {0x1340, 0x0053}, + {0x1341, 0xf4fd}, + {0x1342, 0x0060}, + {0x1343, 0x5816}, + {0x1344, 0x006c}, + {0x1345, 0xbb2e}, + {0x1346, 0x0072}, + {0x1347, 0xecbb}, + {0x1348, 0x0076}, + {0x1349, 0x5d97}, + {0x1500, 0x0702}, + {0x1502, 0x002f}, + {0x1504, 0x0000}, + {0x1510, 0x0064}, + {0x1512, 0x0000}, + {0x1514, 0xdf47}, + {0x1516, 0x079c}, + {0x1518, 0xfbf5}, + {0x151a, 0x00bc}, + {0x151c, 0x3b85}, + {0x151e, 0x02b3}, + {0x1520, 0x3333}, + {0x1522, 0x0000}, + {0x1524, 0x4000}, + {0x1528, 0x0064}, + {0x152a, 0x0000}, + {0x152c, 0x0000}, + {0x152e, 0x0000}, + {0x1530, 0x0000}, + {0x1532, 0x0000}, + {0x1534, 0x0000}, + {0x1536, 0x0000}, + {0x1538, 0x0040}, + {0x1539, 0x0000}, + {0x153a, 0x0040}, + {0x153b, 0x0000}, + {0x153c, 0x0064}, + {0x153e, 0x0bf9}, + {0x1540, 0xb2a9}, + {0x1544, 0x0200}, + {0x1546, 0x0000}, + {0x1548, 0x00ca}, + {0x1552, 0x03ff}, + {0x1554, 0x017f}, + {0x1556, 0x017f}, + {0x155a, 0x0000}, + {0x155c, 0x0000}, + {0x1560, 0x0040}, + {0x1562, 0x0000}, + {0x1570, 0x03ff}, + {0x1571, 0xdcff}, + {0x1572, 0x1e00}, + {0x1573, 0x224f}, + {0x1574, 0x0000}, + {0x1575, 0x0000}, + {0x1576, 0x1e00}, + {0x1577, 0x0000}, + {0x1578, 0x0000}, + {0x1579, 0x1128}, + {0x157a, 0x03ff}, + {0x157b, 0xdcff}, + {0x157c, 0x1e00}, + {0x157d, 0x224f}, + {0x157e, 0x0000}, + {0x157f, 0x0000}, + {0x1580, 0x1e00}, + {0x1581, 0x0000}, + {0x1582, 0x0000}, + {0x1583, 0x1128}, + {0x1590, 0x03ff}, + {0x1591, 0xdcff}, + {0x1592, 0x1e00}, + {0x1593, 0x224f}, + {0x1594, 0x0000}, + {0x1595, 0x0000}, + {0x1596, 0x1e00}, + {0x1597, 0x0000}, + {0x1598, 0x0000}, + {0x1599, 0x1128}, + {0x159a, 0x03ff}, + {0x159b, 0xdcff}, + {0x159c, 0x1e00}, + {0x159d, 0x224f}, + {0x159e, 0x0000}, + {0x159f, 0x0000}, + {0x15a0, 0x1e00}, + {0x15a1, 0x0000}, + {0x15a2, 0x0000}, + {0x15a3, 0x1128}, + {0x15b0, 0x007f}, + {0x15b1, 0xffff}, + {0x15b2, 0x007f}, + {0x15b3, 0xffff}, + {0x15b4, 0x007f}, + {0x15b5, 0xffff}, + {0x15b8, 0x007f}, + {0x15b9, 0xffff}, + {0x15bc, 0x0000}, + {0x15bd, 0x0000}, + {0x15be, 0xff00}, + {0x15bf, 0x0000}, + {0x15c0, 0xff00}, + {0x15c1, 0x0000}, + {0x15c3, 0xfc00}, + {0x15c4, 0xbb80}, + {0x15d0, 0x0000}, + {0x15d1, 0x0000}, + {0x15d2, 0x0000}, + {0x15d3, 0x0000}, + {0x15d4, 0x0000}, + {0x15d5, 0x0000}, + {0x15d6, 0x0000}, + {0x15d7, 0x0000}, + {0x15d8, 0x0200}, + {0x15d9, 0x0000}, + {0x15da, 0x0000}, + {0x15db, 0x0000}, + {0x15dc, 0x0000}, + {0x15dd, 0x0000}, + {0x15de, 0x0000}, + {0x15df, 0x0000}, + {0x15e0, 0x0000}, + {0x15e1, 0x0000}, + {0x15e2, 0x0200}, + {0x15e3, 0x0000}, + {0x15e4, 0x0000}, + {0x15e5, 0x0000}, + {0x15e6, 0x0000}, + {0x15e7, 0x0000}, + {0x15e8, 0x0000}, + {0x15e9, 0x0000}, + {0x15ea, 0x0000}, + {0x15eb, 0x0000}, + {0x15ec, 0x0200}, + {0x15ed, 0x0000}, + {0x15ee, 0x0000}, + {0x15ef, 0x0000}, + {0x15f0, 0x0000}, + {0x15f1, 0x0000}, + {0x15f2, 0x0000}, + {0x15f3, 0x0000}, + {0x15f4, 0x0000}, + {0x15f5, 0x0000}, + {0x15f6, 0x0200}, + {0x15f7, 0x0200}, + {0x15f8, 0x8200}, + {0x15f9, 0x0000}, + {0x1600, 0x007d}, + {0x1601, 0xa178}, + {0x1602, 0x00c2}, + {0x1603, 0x5383}, + {0x1604, 0x0000}, + {0x1605, 0x02c1}, + {0x1606, 0x007d}, + {0x1607, 0xa178}, + {0x1608, 0x00c2}, + {0x1609, 0x5383}, + {0x160a, 0x003e}, + {0x160b, 0xd37d}, + {0x1611, 0x3210}, + {0x1612, 0x7418}, + {0x1613, 0xc0ff}, + {0x1614, 0x0000}, + {0x1615, 0x00ff}, + {0x1616, 0x0000}, + {0x1617, 0x0000}, + {0x1621, 0x6210}, + {0x1622, 0x7418}, + {0x1623, 0xc0ff}, + {0x1624, 0x0000}, + {0x1625, 0x00ff}, + {0x1626, 0x0000}, + {0x1627, 0x0000}, + {0x1631, 0x3a14}, + {0x1632, 0x7418}, + {0x1633, 0xc3ff}, + {0x1634, 0x0000}, + {0x1635, 0x00ff}, + {0x1636, 0x0000}, + {0x1637, 0x0000}, + {0x1638, 0x0000}, + {0x163a, 0x0000}, + {0x163c, 0x0000}, + {0x163e, 0x0000}, + {0x1640, 0x0000}, + {0x1642, 0x0000}, + {0x1644, 0x0000}, + {0x1646, 0x0000}, + {0x1648, 0x0000}, + {0x1650, 0x0000}, + {0x1652, 0x0000}, + {0x1654, 0x0000}, + {0x1656, 0x0000}, + {0x1658, 0x0000}, + {0x1660, 0x0000}, + {0x1662, 0x0000}, + {0x1664, 0x0000}, + {0x1666, 0x0000}, + {0x1668, 0x0000}, + {0x1670, 0x0000}, + {0x1672, 0x0000}, + {0x1674, 0x0000}, + {0x1676, 0x0000}, + {0x1678, 0x0000}, + {0x1680, 0x0000}, + {0x1682, 0x0000}, + {0x1684, 0x0000}, + {0x1686, 0x0000}, + {0x1688, 0x0000}, + {0x1690, 0x0000}, + {0x1692, 0x0000}, + {0x1694, 0x0000}, + {0x1696, 0x0000}, + {0x1698, 0x0000}, + {0x1700, 0x0000}, + {0x1702, 0x0000}, + {0x1704, 0x0000}, + {0x1706, 0x0000}, + {0x1708, 0x0000}, + {0x1710, 0x0000}, + {0x1712, 0x0000}, + {0x1714, 0x0000}, + {0x1716, 0x0000}, + {0x1718, 0x0000}, + {0x1720, 0x0000}, + {0x1722, 0x0000}, + {0x1724, 0x0000}, + {0x1726, 0x0000}, + {0x1728, 0x0000}, + {0x1730, 0x0000}, + {0x1732, 0x0000}, + {0x1734, 0x0000}, + {0x1736, 0x0000}, + {0x1738, 0x0000}, + {0x173a, 0x0000}, + {0x173c, 0x0000}, + {0x173e, 0x0000}, + {0x17bb, 0x0500}, + {0x17bd, 0x0004}, + {0x17bf, 0x0004}, + {0x17c1, 0x0004}, + {0x17c2, 0x7fff}, + {0x17c3, 0x0000}, + {0x17c5, 0x0000}, + {0x17c7, 0x0000}, + {0x17c9, 0x0000}, + {0x17cb, 0x2010}, + {0x17cd, 0x0000}, + {0x17cf, 0x0000}, + {0x17d1, 0x0000}, + {0x17d3, 0x0000}, + {0x17d5, 0x0000}, + {0x17d7, 0x0000}, + {0x17d9, 0x0000}, + {0x17db, 0x0000}, + {0x17dd, 0x0000}, + {0x17df, 0x0000}, + {0x17e1, 0x0000}, + {0x17e3, 0x0000}, + {0x17e5, 0x0000}, + {0x17e7, 0x0000}, + {0x17e9, 0x0000}, + {0x17eb, 0x0000}, + {0x17ed, 0x0000}, + {0x17ef, 0x0000}, + {0x17f1, 0x0000}, + {0x17f3, 0x0000}, + {0x17f5, 0x0000}, + {0x17f7, 0x0000}, + {0x17f9, 0x0000}, + {0x17fb, 0x0000}, + {0x17fd, 0x0000}, + {0x17ff, 0x0000}, + {0x1801, 0x0000}, + {0x1803, 0x0000}, +}; + +static int rt1011_reg_init(struct snd_soc_component *component) +{ + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + + regmap_multi_reg_write(rt1011->regmap, init_list, RT1011_INIT_REG_LEN); + return 0; +} + +static bool rt1011_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT1011_RESET: + case RT1011_SRC_2: + case RT1011_CLK_DET: + case RT1011_SIL_DET: + case RT1011_VERSION_ID: + case RT1011_VENDOR_ID: + case RT1011_DEVICE_ID: + case RT1011_DUM_RO: + case RT1011_DAC_SET_3: + case RT1011_PWM_CAL: + case RT1011_SPK_VOL_TEST_OUT: + case RT1011_VBAT_VOL_DET_1: + case RT1011_VBAT_TEST_OUT_1: + case RT1011_VBAT_TEST_OUT_2: + case RT1011_VBAT_PROTECTION: + case RT1011_VBAT_DET: + case RT1011_BOOST_CON_1: + case RT1011_SHORT_CIRCUIT_DET_1: + case RT1011_SPK_TEMP_PROTECT_3: + case RT1011_SPK_TEMP_PROTECT_6: + case RT1011_SPK_PRO_DC_DET_3: + case RT1011_SPK_PRO_DC_DET_7: + case RT1011_SPK_PRO_DC_DET_8: + case RT1011_SPL_1: + case RT1011_SPL_4: + case RT1011_EXCUR_PROTECT_1: + case RT1011_CROSS_BQ_SET_1: + case RT1011_CROSS_BQ_SET_2: + case RT1011_BQ_SET_0: + case RT1011_BQ_SET_1: + case RT1011_BQ_SET_2: + case RT1011_TEST_PAD_STATUS: + case RT1011_DC_CALIB_CLASSD_1: + case RT1011_DC_CALIB_CLASSD_5: + case RT1011_DC_CALIB_CLASSD_6: + case RT1011_DC_CALIB_CLASSD_7: + case RT1011_DC_CALIB_CLASSD_8: + case RT1011_SINE_GEN_REG_2: + case RT1011_STP_CALIB_RS_TEMP: + case RT1011_SPK_RESISTANCE_1: + case RT1011_SPK_RESISTANCE_2: + case RT1011_SPK_THERMAL: + case RT1011_ALC_BK_GAIN_O: + case RT1011_ALC_BK_GAIN_O_PRE: + case RT1011_SPK_DC_O_23_16: + case RT1011_SPK_DC_O_15_0: + case RT1011_INIT_RECIPROCAL_SYN_24_16: + case RT1011_INIT_RECIPROCAL_SYN_15_0: + case RT1011_SPK_EXCURSION_23_16: + case RT1011_SPK_EXCURSION_15_0: + case RT1011_SEP_MAIN_OUT_23_16: + case RT1011_SEP_MAIN_OUT_15_0: + case RT1011_ALC_DRC_HB_INTERNAL_5: + case RT1011_ALC_DRC_HB_INTERNAL_6: + case RT1011_ALC_DRC_HB_INTERNAL_7: + case RT1011_ALC_DRC_BB_INTERNAL_5: + case RT1011_ALC_DRC_BB_INTERNAL_6: + case RT1011_ALC_DRC_BB_INTERNAL_7: + case RT1011_ALC_DRC_POS_INTERNAL_5: + case RT1011_ALC_DRC_POS_INTERNAL_6: + case RT1011_ALC_DRC_POS_INTERNAL_7: + case RT1011_ALC_DRC_POS_INTERNAL_8: + case RT1011_ALC_DRC_POS_INTERNAL_9: + case RT1011_ALC_DRC_POS_INTERNAL_10: + case RT1011_ALC_DRC_POS_INTERNAL_11: + case RT1011_IRQ_1: + case RT1011_EFUSE_CONTROL_1: + case RT1011_EFUSE_CONTROL_2: + case RT1011_EFUSE_MATCH_DONE ... RT1011_EFUSE_READ_R0_3_15_0: + return true; + + default: + return false; + } +} + +static bool rt1011_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT1011_RESET: + case RT1011_CLK_1: + case RT1011_CLK_2: + case RT1011_CLK_3: + case RT1011_CLK_4: + case RT1011_PLL_1: + case RT1011_PLL_2: + case RT1011_SRC_1: + case RT1011_SRC_2: + case RT1011_SRC_3: + case RT1011_CLK_DET: + case RT1011_SIL_DET: + case RT1011_PRIV_INDEX: + case RT1011_PRIV_DATA: + case RT1011_CUSTOMER_ID: + case RT1011_FM_VER: + case RT1011_VERSION_ID: + case RT1011_VENDOR_ID: + case RT1011_DEVICE_ID: + case RT1011_DUM_RW_0: + case RT1011_DUM_YUN: + case RT1011_DUM_RW_1: + case RT1011_DUM_RO: + case RT1011_MAN_I2C_DEV: + case RT1011_DAC_SET_1: + case RT1011_DAC_SET_2: + case RT1011_DAC_SET_3: + case RT1011_ADC_SET: + case RT1011_ADC_SET_1: + case RT1011_ADC_SET_2: + case RT1011_ADC_SET_3: + case RT1011_ADC_SET_4: + case RT1011_ADC_SET_5: + case RT1011_TDM_TOTAL_SET: + case RT1011_TDM1_SET_TCON: + case RT1011_TDM1_SET_1: + case RT1011_TDM1_SET_2: + case RT1011_TDM1_SET_3: + case RT1011_TDM1_SET_4: + case RT1011_TDM1_SET_5: + case RT1011_TDM2_SET_1: + case RT1011_TDM2_SET_2: + case RT1011_TDM2_SET_3: + case RT1011_TDM2_SET_4: + case RT1011_TDM2_SET_5: + case RT1011_PWM_CAL: + case RT1011_MIXER_1: + case RT1011_MIXER_2: + case RT1011_ADRC_LIMIT: + case RT1011_A_PRO: + case RT1011_A_TIMING_1: + case RT1011_A_TIMING_2: + case RT1011_A_TEMP_SEN: + case RT1011_SPK_VOL_DET_1: + case RT1011_SPK_VOL_DET_2: + case RT1011_SPK_VOL_TEST_OUT: + case RT1011_VBAT_VOL_DET_1: + case RT1011_VBAT_VOL_DET_2: + case RT1011_VBAT_TEST_OUT_1: + case RT1011_VBAT_TEST_OUT_2: + case RT1011_VBAT_PROTECTION: + case RT1011_VBAT_DET: + case RT1011_POWER_1: + case RT1011_POWER_2: + case RT1011_POWER_3: + case RT1011_POWER_4: + case RT1011_POWER_5: + case RT1011_POWER_6: + case RT1011_POWER_7: + case RT1011_POWER_8: + case RT1011_POWER_9: + case RT1011_CLASS_D_POS: + case RT1011_BOOST_CON_1: + case RT1011_BOOST_CON_2: + case RT1011_ANALOG_CTRL: + case RT1011_POWER_SEQ: + case RT1011_SHORT_CIRCUIT_DET_1: + case RT1011_SHORT_CIRCUIT_DET_2: + case RT1011_SPK_TEMP_PROTECT_0: + case RT1011_SPK_TEMP_PROTECT_1: + case RT1011_SPK_TEMP_PROTECT_2: + case RT1011_SPK_TEMP_PROTECT_3: + case RT1011_SPK_TEMP_PROTECT_4: + case RT1011_SPK_TEMP_PROTECT_5: + case RT1011_SPK_TEMP_PROTECT_6: + case RT1011_SPK_TEMP_PROTECT_7: + case RT1011_SPK_TEMP_PROTECT_8: + case RT1011_SPK_TEMP_PROTECT_9: + case RT1011_SPK_PRO_DC_DET_1: + case RT1011_SPK_PRO_DC_DET_2: + case RT1011_SPK_PRO_DC_DET_3: + case RT1011_SPK_PRO_DC_DET_4: + case RT1011_SPK_PRO_DC_DET_5: + case RT1011_SPK_PRO_DC_DET_6: + case RT1011_SPK_PRO_DC_DET_7: + case RT1011_SPK_PRO_DC_DET_8: + case RT1011_SPL_1: + case RT1011_SPL_2: + case RT1011_SPL_3: + case RT1011_SPL_4: + case RT1011_THER_FOLD_BACK_1: + case RT1011_THER_FOLD_BACK_2: + case RT1011_EXCUR_PROTECT_1: + case RT1011_EXCUR_PROTECT_2: + case RT1011_EXCUR_PROTECT_3: + case RT1011_EXCUR_PROTECT_4: + case RT1011_BAT_GAIN_1: + case RT1011_BAT_GAIN_2: + case RT1011_BAT_GAIN_3: + case RT1011_BAT_GAIN_4: + case RT1011_BAT_GAIN_5: + case RT1011_BAT_GAIN_6: + case RT1011_BAT_GAIN_7: + case RT1011_BAT_GAIN_8: + case RT1011_BAT_GAIN_9: + case RT1011_BAT_GAIN_10: + case RT1011_BAT_GAIN_11: + case RT1011_BAT_RT_THMAX_1: + case RT1011_BAT_RT_THMAX_2: + case RT1011_BAT_RT_THMAX_3: + case RT1011_BAT_RT_THMAX_4: + case RT1011_BAT_RT_THMAX_5: + case RT1011_BAT_RT_THMAX_6: + case RT1011_BAT_RT_THMAX_7: + case RT1011_BAT_RT_THMAX_8: + case RT1011_BAT_RT_THMAX_9: + case RT1011_BAT_RT_THMAX_10: + case RT1011_BAT_RT_THMAX_11: + case RT1011_BAT_RT_THMAX_12: + case RT1011_SPREAD_SPECTURM: + case RT1011_PRO_GAIN_MODE: + case RT1011_RT_DRC_CROSS: + case RT1011_RT_DRC_HB_1: + case RT1011_RT_DRC_HB_2: + case RT1011_RT_DRC_HB_3: + case RT1011_RT_DRC_HB_4: + case RT1011_RT_DRC_HB_5: + case RT1011_RT_DRC_HB_6: + case RT1011_RT_DRC_HB_7: + case RT1011_RT_DRC_HB_8: + case RT1011_RT_DRC_BB_1: + case RT1011_RT_DRC_BB_2: + case RT1011_RT_DRC_BB_3: + case RT1011_RT_DRC_BB_4: + case RT1011_RT_DRC_BB_5: + case RT1011_RT_DRC_BB_6: + case RT1011_RT_DRC_BB_7: + case RT1011_RT_DRC_BB_8: + case RT1011_RT_DRC_POS_1: + case RT1011_RT_DRC_POS_2: + case RT1011_RT_DRC_POS_3: + case RT1011_RT_DRC_POS_4: + case RT1011_RT_DRC_POS_5: + case RT1011_RT_DRC_POS_6: + case RT1011_RT_DRC_POS_7: + case RT1011_RT_DRC_POS_8: + case RT1011_CROSS_BQ_SET_1: + case RT1011_CROSS_BQ_SET_2: + case RT1011_BQ_SET_0: + case RT1011_BQ_SET_1: + case RT1011_BQ_SET_2: + case RT1011_BQ_PRE_GAIN_28_16: + case RT1011_BQ_PRE_GAIN_15_0: + case RT1011_BQ_POST_GAIN_28_16: + case RT1011_BQ_POST_GAIN_15_0: + case RT1011_BQ_H0_28_16 ... RT1011_BQ_A2_15_0: + case RT1011_BQ_1_H0_28_16 ... RT1011_BQ_1_A2_15_0: + case RT1011_BQ_2_H0_28_16 ... RT1011_BQ_2_A2_15_0: + case RT1011_BQ_3_H0_28_16 ... RT1011_BQ_3_A2_15_0: + case RT1011_BQ_4_H0_28_16 ... RT1011_BQ_4_A2_15_0: + case RT1011_BQ_5_H0_28_16 ... RT1011_BQ_5_A2_15_0: + case RT1011_BQ_6_H0_28_16 ... RT1011_BQ_6_A2_15_0: + case RT1011_BQ_7_H0_28_16 ... RT1011_BQ_7_A2_15_0: + case RT1011_BQ_8_H0_28_16 ... RT1011_BQ_8_A2_15_0: + case RT1011_BQ_9_H0_28_16 ... RT1011_BQ_9_A2_15_0: + case RT1011_BQ_10_H0_28_16 ... RT1011_BQ_10_A2_15_0: + case RT1011_TEST_PAD_STATUS ... RT1011_PLL_INTERNAL_SET: + case RT1011_TEST_OUT_1 ... RT1011_TEST_OUT_3: + case RT1011_DC_CALIB_CLASSD_1 ... RT1011_DC_CALIB_CLASSD_10: + case RT1011_CLASSD_INTERNAL_SET_1 ... RT1011_VREF_LV_1: + case RT1011_SMART_BOOST_TIMING_1 ... RT1011_SMART_BOOST_TIMING_36: + case RT1011_SINE_GEN_REG_1 ... RT1011_SINE_GEN_REG_3: + case RT1011_STP_INITIAL_RS_TEMP ... RT1011_SPK_THERMAL: + case RT1011_STP_OTP_TH ... RT1011_INIT_RECIPROCAL_SYN_15_0: + case RT1011_STP_BQ_1_A1_L_28_16 ... RT1011_STP_BQ_1_H0_R_15_0: + case RT1011_STP_BQ_2_A1_L_28_16 ... RT1011_SEP_RE_REG_15_0: + case RT1011_DRC_CF_PARAMS_1 ... RT1011_DRC_CF_PARAMS_12: + case RT1011_ALC_DRC_HB_INTERNAL_1 ... RT1011_ALC_DRC_HB_INTERNAL_7: + case RT1011_ALC_DRC_BB_INTERNAL_1 ... RT1011_ALC_DRC_BB_INTERNAL_7: + case RT1011_ALC_DRC_POS_INTERNAL_1 ... RT1011_ALC_DRC_POS_INTERNAL_8: + case RT1011_ALC_DRC_POS_INTERNAL_9 ... RT1011_BQ_1_PARAMS_CHECK_5: + case RT1011_BQ_2_PARAMS_CHECK_1 ... RT1011_BQ_2_PARAMS_CHECK_5: + case RT1011_BQ_3_PARAMS_CHECK_1 ... RT1011_BQ_3_PARAMS_CHECK_5: + case RT1011_BQ_4_PARAMS_CHECK_1 ... RT1011_BQ_4_PARAMS_CHECK_5: + case RT1011_BQ_5_PARAMS_CHECK_1 ... RT1011_BQ_5_PARAMS_CHECK_5: + case RT1011_BQ_6_PARAMS_CHECK_1 ... RT1011_BQ_6_PARAMS_CHECK_5: + case RT1011_BQ_7_PARAMS_CHECK_1 ... RT1011_BQ_7_PARAMS_CHECK_5: + case RT1011_BQ_8_PARAMS_CHECK_1 ... RT1011_BQ_8_PARAMS_CHECK_5: + case RT1011_BQ_9_PARAMS_CHECK_1 ... RT1011_BQ_9_PARAMS_CHECK_5: + case RT1011_BQ_10_PARAMS_CHECK_1 ... RT1011_BQ_10_PARAMS_CHECK_5: + case RT1011_IRQ_1 ... RT1011_PART_NUMBER_EFUSE: + case RT1011_EFUSE_CONTROL_1 ... RT1011_EFUSE_READ_R0_3_15_0: + return true; + default: + return false; + } +} + +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9435, 37, 0); +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1739, 37, 0); + +static const char * const rt1011_din_source_select[] = { + "Left", + "Right", + "Left + Right average", +}; + +static SOC_ENUM_SINGLE_DECL(rt1011_din_source_enum, RT1011_CROSS_BQ_SET_1, 5, + rt1011_din_source_select); + +static const char * const rt1011_tdm_data_out_select[] = { + "TDM_O_LR", "BQ1", "DVOL", "BQ10", "ALC", "DMIX", "ADC_SRC_LR", + "ADC_O_LR", "ADC_MONO", "RSPK_BPF_LR", "DMIX_ADD", "ENVELOPE_FS", + "SEP_O_GAIN", "ALC_BK_GAIN", "STP_V_C", "DMIX_ABST" +}; + +static const char * const rt1011_tdm_l_ch_data_select[] = { + "Slot0", "Slot1", "Slot2", "Slot3", "Slot4", "Slot5", "Slot6", "Slot7" +}; +static SOC_ENUM_SINGLE_DECL(rt1011_tdm1_l_dac1_enum, RT1011_TDM1_SET_4, 12, + rt1011_tdm_l_ch_data_select); +static SOC_ENUM_SINGLE_DECL(rt1011_tdm2_l_dac1_enum, RT1011_TDM2_SET_4, 12, + rt1011_tdm_l_ch_data_select); + +static SOC_ENUM_SINGLE_DECL(rt1011_tdm1_adc1_dat_enum, + RT1011_ADCDAT_OUT_SOURCE, 0, rt1011_tdm_data_out_select); +static SOC_ENUM_SINGLE_DECL(rt1011_tdm1_adc1_loc_enum, RT1011_TDM1_SET_2, 0, + rt1011_tdm_l_ch_data_select); + +static const char * const rt1011_adc_data_mode_select[] = { + "Stereo", "Mono" +}; +static SOC_ENUM_SINGLE_DECL(rt1011_adc_dout_mode_enum, RT1011_TDM1_SET_1, 12, + rt1011_adc_data_mode_select); + +static const char * const rt1011_tdm_adc_data_len_control[] = { + "1CH", "2CH", "3CH", "4CH", "5CH", "6CH", "7CH", "8CH" +}; +static SOC_ENUM_SINGLE_DECL(rt1011_tdm1_dout_len_enum, RT1011_TDM1_SET_2, 13, + rt1011_tdm_adc_data_len_control); +static SOC_ENUM_SINGLE_DECL(rt1011_tdm2_dout_len_enum, RT1011_TDM2_SET_2, 13, + rt1011_tdm_adc_data_len_control); + +static const char * const rt1011_tdm_adc_swap_select[] = { + "L/R", "R/L", "L/L", "R/R" +}; + +static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum, RT1011_TDM1_SET_3, 6, + rt1011_tdm_adc_swap_select); + +static void rt1011_reset(struct regmap *regmap) +{ + regmap_write(regmap, RT1011_RESET, 0); +} + +static int rt1011_recv_spk_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct rt1011_priv *rt1011 = + snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rt1011->recv_spk_mode; + + return 0; +} + +static int rt1011_recv_spk_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct rt1011_priv *rt1011 = + snd_soc_component_get_drvdata(component); + + if (ucontrol->value.integer.value[0] == rt1011->recv_spk_mode) + return 0; + + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { + rt1011->recv_spk_mode = ucontrol->value.integer.value[0]; + + if (rt1011->recv_spk_mode) { + + /* 1: recevier mode on */ + snd_soc_component_update_bits(component, + RT1011_CLASSD_INTERNAL_SET_3, + RT1011_REG_GAIN_CLASSD_RI_SPK_MASK, + RT1011_REG_GAIN_CLASSD_RI_410K); + snd_soc_component_update_bits(component, + RT1011_CLASSD_INTERNAL_SET_1, + RT1011_RECV_MODE_SPK_MASK, + RT1011_RECV_MODE); + } else { + /* 0: speaker mode on */ + snd_soc_component_update_bits(component, + RT1011_CLASSD_INTERNAL_SET_3, + RT1011_REG_GAIN_CLASSD_RI_SPK_MASK, + RT1011_REG_GAIN_CLASSD_RI_72P5K); + snd_soc_component_update_bits(component, + RT1011_CLASSD_INTERNAL_SET_1, + RT1011_RECV_MODE_SPK_MASK, + RT1011_SPK_MODE); + } + } + + return 0; +} + +static bool rt1011_validate_bq_drc_coeff(unsigned short reg) +{ + if ((reg == RT1011_DAC_SET_1) | + (reg >= RT1011_ADC_SET && reg <= RT1011_ADC_SET_1) | + (reg == RT1011_ADC_SET_4) | (reg == RT1011_ADC_SET_5) | + (reg == RT1011_MIXER_1) | + (reg == RT1011_A_TIMING_1) | (reg >= RT1011_POWER_7 && + reg <= RT1011_POWER_8) | + (reg == RT1011_CLASS_D_POS) | (reg == RT1011_ANALOG_CTRL) | + (reg >= RT1011_SPK_TEMP_PROTECT_0 && + reg <= RT1011_SPK_TEMP_PROTECT_6) | + (reg >= RT1011_SPK_PRO_DC_DET_5 && reg <= RT1011_BAT_GAIN_1) | + (reg >= RT1011_RT_DRC_CROSS && reg <= RT1011_RT_DRC_POS_8) | + (reg >= RT1011_CROSS_BQ_SET_1 && reg <= RT1011_BQ_10_A2_15_0) | + (reg >= RT1011_SMART_BOOST_TIMING_1 && + reg <= RT1011_SMART_BOOST_TIMING_36) | + (reg == RT1011_SINE_GEN_REG_1) | + (reg >= RT1011_STP_ALPHA_RECIPROCAL_MSB && + reg <= RT1011_BQ_6_PARAMS_CHECK_5) | + (reg >= RT1011_BQ_7_PARAMS_CHECK_1 && + reg <= RT1011_BQ_10_PARAMS_CHECK_5)) + return true; + + return false; +} + +static int rt1011_bq_drc_coeff_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct rt1011_priv *rt1011 = + snd_soc_component_get_drvdata(component); + struct rt1011_bq_drc_params *bq_drc_info; + struct rt1011_bq_drc_params *params = + (struct rt1011_bq_drc_params *)ucontrol->value.integer.value; + unsigned int i, mode_idx = 0; + + if (strstr(ucontrol->id.name, "AdvanceMode Initial Set")) + mode_idx = RT1011_ADVMODE_INITIAL_SET; + else if (strstr(ucontrol->id.name, "AdvanceMode SEP BQ Coeff")) + mode_idx = RT1011_ADVMODE_SEP_BQ_COEFF; + else if (strstr(ucontrol->id.name, "AdvanceMode EQ BQ Coeff")) + mode_idx = RT1011_ADVMODE_EQ_BQ_COEFF; + else if (strstr(ucontrol->id.name, "AdvanceMode BQ UI Coeff")) + mode_idx = RT1011_ADVMODE_BQ_UI_COEFF; + else if (strstr(ucontrol->id.name, "AdvanceMode SmartBoost Coeff")) + mode_idx = RT1011_ADVMODE_SMARTBOOST_COEFF; + else + return -EINVAL; + + pr_info("%s, id.name=%s, mode_idx=%d\n", __func__, + ucontrol->id.name, mode_idx); + bq_drc_info = rt1011->bq_drc_params[mode_idx]; + + for (i = 0; i < RT1011_BQ_DRC_NUM; i++) { + params[i].reg = cpu_to_le16(bq_drc_info[i].reg); + params[i].val = cpu_to_le16(bq_drc_info[i].val); + } + + return 0; +} + +static int rt1011_bq_drc_coeff_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct rt1011_priv *rt1011 = + snd_soc_component_get_drvdata(component); + struct rt1011_bq_drc_params *bq_drc_info; + struct rt1011_bq_drc_params *params = + (struct rt1011_bq_drc_params *)ucontrol->value.integer.value; + unsigned int i, mode_idx = 0; + + if (!component->card->instantiated) + return 0; + + if (strstr(ucontrol->id.name, "AdvanceMode Initial Set")) + mode_idx = RT1011_ADVMODE_INITIAL_SET; + else if (strstr(ucontrol->id.name, "AdvanceMode SEP BQ Coeff")) + mode_idx = RT1011_ADVMODE_SEP_BQ_COEFF; + else if (strstr(ucontrol->id.name, "AdvanceMode EQ BQ Coeff")) + mode_idx = RT1011_ADVMODE_EQ_BQ_COEFF; + else if (strstr(ucontrol->id.name, "AdvanceMode BQ UI Coeff")) + mode_idx = RT1011_ADVMODE_BQ_UI_COEFF; + else if (strstr(ucontrol->id.name, "AdvanceMode SmartBoost Coeff")) + mode_idx = RT1011_ADVMODE_SMARTBOOST_COEFF; + else + return -EINVAL; + + bq_drc_info = rt1011->bq_drc_params[mode_idx]; + memset(bq_drc_info, 0, + sizeof(struct rt1011_bq_drc_params) * RT1011_BQ_DRC_NUM); + + pr_info("%s, id.name=%s, mode_idx=%d\n", __func__, + ucontrol->id.name, mode_idx); + for (i = 0; i < RT1011_BQ_DRC_NUM; i++) { + bq_drc_info[i].reg = le16_to_cpu(params[i].reg); + bq_drc_info[i].val = le16_to_cpu(params[i].val); + } + + for (i = 0; i < RT1011_BQ_DRC_NUM; i++) { + if (bq_drc_info[i].reg == 0) + break; + else if (rt1011_validate_bq_drc_coeff(bq_drc_info[i].reg)) { + snd_soc_component_write(component, bq_drc_info[i].reg, + bq_drc_info[i].val); + } + } + + return 0; +} + +static int rt1011_bq_drc_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 128; + uinfo->value.integer.max = 0x17ffffff; + + return 0; +} + +#define RT1011_BQ_DRC(xname) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = rt1011_bq_drc_info, \ + .get = rt1011_bq_drc_coeff_get, \ + .put = rt1011_bq_drc_coeff_put \ +} + +static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = 0; + + return 0; +} + +static int rt1011_r0_cali_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + + if (!component->card->instantiated) + return 0; + + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF && + ucontrol->value.integer.value[0]) + rt1011_calibrate(rt1011, 1); + + return 0; +} + +static int rt1011_r0_load(struct rt1011_priv *rt1011) +{ + if (!rt1011->r0_reg) + return -EINVAL; + + /* write R0 to register */ + regmap_write(rt1011->regmap, RT1011_INIT_RECIPROCAL_REG_24_16, + ((rt1011->r0_reg>>16) & 0x1ff)); + regmap_write(rt1011->regmap, RT1011_INIT_RECIPROCAL_REG_15_0, + (rt1011->r0_reg & 0xffff)); + regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_4, 0x4080); + + return 0; +} + +static int rt1011_r0_load_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rt1011->r0_reg; + + return 0; +} + +static int rt1011_r0_load_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + struct device *dev; + unsigned int r0_integer, r0_factor, format; + + if (ucontrol->value.integer.value[0] == rt1011->r0_reg) + return 0; + + if (!component->card->instantiated) + return 0; + + dev = regmap_get_device(rt1011->regmap); + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { + rt1011->r0_reg = ucontrol->value.integer.value[0]; + + format = 2147483648; /* 2^24 * 128 */ + r0_integer = format / rt1011->r0_reg / 128; + r0_factor = ((format / rt1011->r0_reg * 100) / 128) + - (r0_integer * 100); + dev_info(dev, "New r0 resistance about %d.%02d ohm, reg=0x%X\n", + r0_integer, r0_factor, rt1011->r0_reg); + + if (rt1011->r0_reg) + rt1011_r0_load(rt1011); + } + + return 0; +} + +static int rt1011_r0_load_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.max = 0x1ffffff; + + return 0; +} + +#define RT1011_R0_LOAD(xname) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = rt1011_r0_load_info, \ + .get = rt1011_r0_load_mode_get, \ + .put = rt1011_r0_load_mode_put \ +} + +static const struct snd_kcontrol_new rt1011_snd_controls[] = { + /* I2S Data In Selection */ + SOC_ENUM("DIN Source", rt1011_din_source_enum), + + /* TDM Data In Selection */ + SOC_ENUM("TDM1 DIN Source", rt1011_tdm1_l_dac1_enum), + SOC_ENUM("TDM2 DIN Source", rt1011_tdm2_l_dac1_enum), + + /* TDM1 Data Out Selection */ + SOC_ENUM("TDM1 DOUT Source", rt1011_tdm1_adc1_dat_enum), + SOC_ENUM("TDM1 DOUT Location", rt1011_tdm1_adc1_loc_enum), + SOC_ENUM("TDM1 ADCDAT Swap Select", rt1011_tdm_adc1_1_enum), + + /* Data Out Mode */ + SOC_ENUM("I2S ADC DOUT Mode", rt1011_adc_dout_mode_enum), + SOC_ENUM("TDM1 DOUT Length", rt1011_tdm1_dout_len_enum), + SOC_ENUM("TDM2 DOUT Length", rt1011_tdm2_dout_len_enum), + + /* Speaker/Receiver Mode */ + SOC_SINGLE_EXT("RECV SPK Mode", SND_SOC_NOPM, 0, 1, 0, + rt1011_recv_spk_mode_get, rt1011_recv_spk_mode_put), + + /* BiQuad/DRC/SmartBoost Settings */ + RT1011_BQ_DRC("AdvanceMode Initial Set"), + RT1011_BQ_DRC("AdvanceMode SEP BQ Coeff"), + RT1011_BQ_DRC("AdvanceMode EQ BQ Coeff"), + RT1011_BQ_DRC("AdvanceMode BQ UI Coeff"), + RT1011_BQ_DRC("AdvanceMode SmartBoost Coeff"), + + /* R0 */ + SOC_SINGLE_EXT("R0 Calibration", SND_SOC_NOPM, 0, 1, 0, + rt1011_r0_cali_get, rt1011_r0_cali_put), + RT1011_R0_LOAD("R0 Load Mode"), +}; + +static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(source->dapm); + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + + if (rt1011->sysclk_src == RT1011_FS_SYS_PRE_S_PLL1) + return 1; + else + return 0; +} + +static int rt1011_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_update_bits(component, + RT1011_SPK_TEMP_PROTECT_0, + RT1011_STP_EN_MASK | RT1011_STP_RS_CLB_EN_MASK, + RT1011_STP_EN | RT1011_STP_RS_CLB_EN); + snd_soc_component_update_bits(component, RT1011_POWER_9, + RT1011_POW_MNL_SDB_MASK, RT1011_POW_MNL_SDB); + msleep(50); + snd_soc_component_update_bits(component, + RT1011_CLASSD_INTERNAL_SET_1, + RT1011_DRIVER_READY_SPK, RT1011_DRIVER_READY_SPK); + break; + case SND_SOC_DAPM_PRE_PMD: + snd_soc_component_update_bits(component, RT1011_POWER_9, + RT1011_POW_MNL_SDB_MASK, 0); + snd_soc_component_update_bits(component, + RT1011_SPK_TEMP_PROTECT_0, + RT1011_STP_EN_MASK | RT1011_STP_RS_CLB_EN_MASK, 0); + msleep(200); + snd_soc_component_update_bits(component, + RT1011_CLASSD_INTERNAL_SET_1, + RT1011_DRIVER_READY_SPK, 0); + break; + + default: + return 0; + } + + return 0; +} + + +static const struct snd_soc_dapm_widget rt1011_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("LDO2", RT1011_POWER_1, + RT1011_POW_LDO2_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ISENSE SPK", RT1011_POWER_1, + RT1011_POW_ISENSE_SPK_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("VSENSE SPK", RT1011_POWER_1, + RT1011_POW_VSENSE_SPK_BIT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("PLL", RT1011_POWER_2, + RT1011_PLLEN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BG", RT1011_POWER_2, + RT1011_POW_BG_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BG MBIAS", RT1011_POWER_2, + RT1011_POW_BG_MBIAS_LV_BIT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("DET VBAT", RT1011_POWER_3, + RT1011_POW_DET_VBAT_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MBIAS", RT1011_POWER_3, + RT1011_POW_MBIAS_LV_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC I", RT1011_POWER_3, + RT1011_POW_ADC_I_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC V", RT1011_POWER_3, + RT1011_POW_ADC_V_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC T", RT1011_POWER_3, + RT1011_POW_ADC_T_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DITHER ADC T", RT1011_POWER_3, + RT1011_POWD_ADC_T_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MIX I", RT1011_POWER_3, + RT1011_POW_MIX_I_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MIX V", RT1011_POWER_3, + RT1011_POW_MIX_V_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("SUM I", RT1011_POWER_3, + RT1011_POW_SUM_I_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("SUM V", RT1011_POWER_3, + RT1011_POW_SUM_V_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MIX T", RT1011_POWER_3, + RT1011_POW_MIX_T_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("VREF", RT1011_POWER_3, + RT1011_POW_VREF_LV_BIT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("BOOST SWR", RT1011_POWER_4, + RT1011_POW_EN_SWR_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BGOK SWR", RT1011_POWER_4, + RT1011_POW_EN_PASS_BGOK_SWR_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("VPOK SWR", RT1011_POWER_4, + RT1011_POW_EN_PASS_VPOK_SWR_BIT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("TEMP REG", RT1011_A_TEMP_SEN, + RT1011_POW_TEMP_REG_BIT, 0, NULL, 0), + + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + /* Digital Interface */ + SND_SOC_DAPM_SUPPLY("DAC Power", RT1011_POWER_1, + RT1011_POW_DAC_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CLK12M", RT1011_POWER_1, + RT1011_POW_CLK12M_BIT, 0, NULL, 0), + SND_SOC_DAPM_DAC_E("DAC", NULL, RT1011_DAC_SET_3, + RT1011_DA_MUTE_EN_SFT, 1, rt1011_dac_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + + /* Output Lines */ + SND_SOC_DAPM_OUTPUT("SPO"), +}; + +static const struct snd_soc_dapm_route rt1011_dapm_routes[] = { + + { "DAC", NULL, "AIF1RX" }, + { "DAC", NULL, "DAC Power" }, + { "DAC", NULL, "LDO2" }, + { "DAC", NULL, "ISENSE SPK" }, + { "DAC", NULL, "VSENSE SPK" }, + { "DAC", NULL, "CLK12M" }, + + { "DAC", NULL, "PLL", rt1011_is_sys_clk_from_pll }, + { "DAC", NULL, "BG" }, + { "DAC", NULL, "BG MBIAS" }, + + { "DAC", NULL, "BOOST SWR" }, + { "DAC", NULL, "BGOK SWR" }, + { "DAC", NULL, "VPOK SWR" }, + + { "DAC", NULL, "DET VBAT" }, + { "DAC", NULL, "MBIAS" }, + { "DAC", NULL, "VREF" }, + { "DAC", NULL, "ADC I" }, + { "DAC", NULL, "ADC V" }, + { "DAC", NULL, "ADC T" }, + { "DAC", NULL, "DITHER ADC T" }, + { "DAC", NULL, "MIX I" }, + { "DAC", NULL, "MIX V" }, + { "DAC", NULL, "SUM I" }, + { "DAC", NULL, "SUM V" }, + { "DAC", NULL, "MIX T" }, + + { "DAC", NULL, "TEMP REG" }, + + { "SPO", NULL, "DAC" }, +}; + +static int rt1011_get_clk_info(int sclk, int rate) +{ + int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; + + if (sclk <= 0 || rate <= 0) + return -EINVAL; + + rate = rate << 8; + for (i = 0; i < ARRAY_SIZE(pd); i++) + if (sclk == rate * pd[i]) + return i; + + return -EINVAL; +} + +static int rt1011_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + unsigned int val_len = 0, ch_len = 0, val_clk, mask_clk; + int pre_div, bclk_ms, frame_size; + + rt1011->lrck = params_rate(params); + pre_div = rt1011_get_clk_info(rt1011->sysclk, rt1011->lrck); + if (pre_div < 0) { + dev_warn(component->dev, "Force using PLL "); + snd_soc_dai_set_pll(dai, 0, RT1011_PLL1_S_BCLK, + rt1011->lrck * 64, rt1011->lrck * 256); + snd_soc_dai_set_sysclk(dai, RT1011_FS_SYS_PRE_S_PLL1, + rt1011->lrck * 256, SND_SOC_CLOCK_IN); + pre_div = 0; + } + frame_size = snd_soc_params_to_frame_size(params); + if (frame_size < 0) { + dev_err(component->dev, "Unsupported frame size: %d\n", + frame_size); + return -EINVAL; + } + + bclk_ms = frame_size > 32; + rt1011->bclk = rt1011->lrck * (32 << bclk_ms); + + dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", + bclk_ms, pre_div, dai->id); + + dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n", + rt1011->lrck, pre_div, dai->id); + + switch (params_width(params)) { + case 16: + val_len |= RT1011_I2S_TX_DL_16B; + val_len |= RT1011_I2S_RX_DL_16B; + ch_len |= RT1011_I2S_CH_TX_LEN_16B; + ch_len |= RT1011_I2S_CH_RX_LEN_16B; + break; + case 20: + val_len |= RT1011_I2S_TX_DL_20B; + val_len |= RT1011_I2S_RX_DL_20B; + ch_len |= RT1011_I2S_CH_TX_LEN_20B; + ch_len |= RT1011_I2S_CH_RX_LEN_20B; + break; + case 24: + val_len |= RT1011_I2S_TX_DL_24B; + val_len |= RT1011_I2S_RX_DL_24B; + ch_len |= RT1011_I2S_CH_TX_LEN_24B; + ch_len |= RT1011_I2S_CH_RX_LEN_24B; + break; + case 32: + val_len |= RT1011_I2S_TX_DL_32B; + val_len |= RT1011_I2S_RX_DL_32B; + ch_len |= RT1011_I2S_CH_TX_LEN_32B; + ch_len |= RT1011_I2S_CH_RX_LEN_32B; + break; + case 8: + val_len |= RT1011_I2S_TX_DL_8B; + val_len |= RT1011_I2S_RX_DL_8B; + ch_len |= RT1011_I2S_CH_TX_LEN_8B; + ch_len |= RT1011_I2S_CH_RX_LEN_8B; + break; + default: + return -EINVAL; + } + + switch (dai->id) { + case RT1011_AIF1: + mask_clk = RT1011_FS_SYS_DIV_MASK; + val_clk = pre_div << RT1011_FS_SYS_DIV_SFT; + snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET, + RT1011_I2S_TX_DL_MASK | RT1011_I2S_RX_DL_MASK, + val_len); + snd_soc_component_update_bits(component, RT1011_TDM1_SET_1, + RT1011_I2S_CH_TX_LEN_MASK | + RT1011_I2S_CH_RX_LEN_MASK, + ch_len); + break; + default: + dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + + snd_soc_component_update_bits(component, + RT1011_CLK_2, mask_clk, val_clk); + + return 0; +} + +static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + unsigned int reg_val = 0, reg_bclk_inv = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + reg_val |= RT1011_I2S_TDM_MS_S; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + reg_bclk_inv |= RT1011_TDM_INV_BCLK; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_LEFT_J: + reg_val |= RT1011_I2S_TDM_DF_LEFT; + break; + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT1011_I2S_TDM_DF_PCM_A; + break; + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT1011_I2S_TDM_DF_PCM_B; + break; + default: + return -EINVAL; + } + + switch (dai->id) { + case RT1011_AIF1: + snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET, + RT1011_I2S_TDM_MS_MASK | RT1011_I2S_TDM_DF_MASK, + reg_val); + snd_soc_component_update_bits(component, RT1011_TDM1_SET_1, + RT1011_TDM_INV_BCLK_MASK, reg_bclk_inv); + snd_soc_component_update_bits(component, RT1011_TDM2_SET_1, + RT1011_TDM_INV_BCLK_MASK, reg_bclk_inv); + break; + default: + dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + return 0; +} + +static int rt1011_set_component_sysclk(struct snd_soc_component *component, + int clk_id, int source, unsigned int freq, int dir) +{ + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + unsigned int reg_val = 0; + + if (freq == rt1011->sysclk && clk_id == rt1011->sysclk_src) + return 0; + + /* disable MCLK detect in default */ + snd_soc_component_update_bits(component, RT1011_CLK_DET, + RT1011_EN_MCLK_DET_MASK, 0); + + switch (clk_id) { + case RT1011_FS_SYS_PRE_S_MCLK: + reg_val |= RT1011_FS_SYS_PRE_MCLK; + snd_soc_component_update_bits(component, RT1011_CLK_DET, + RT1011_EN_MCLK_DET_MASK, RT1011_EN_MCLK_DET); + break; + case RT1011_FS_SYS_PRE_S_BCLK: + reg_val |= RT1011_FS_SYS_PRE_BCLK; + break; + case RT1011_FS_SYS_PRE_S_PLL1: + reg_val |= RT1011_FS_SYS_PRE_PLL1; + break; + case RT1011_FS_SYS_PRE_S_RCCLK: + reg_val |= RT1011_FS_SYS_PRE_RCCLK; + break; + default: + dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + snd_soc_component_update_bits(component, RT1011_CLK_2, + RT1011_FS_SYS_PRE_MASK, reg_val); + rt1011->sysclk = freq; + rt1011->sysclk_src = clk_id; + + dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n", + freq, clk_id); + + return 0; +} + +static int rt1011_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, unsigned int freq_in, + unsigned int freq_out) +{ + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + struct rl6231_pll_code pll_code; + int ret; + + if (source == rt1011->pll_src && freq_in == rt1011->pll_in && + freq_out == rt1011->pll_out) + return 0; + + if (!freq_in || !freq_out) { + dev_dbg(component->dev, "PLL disabled\n"); + + rt1011->pll_in = 0; + rt1011->pll_out = 0; + snd_soc_component_update_bits(component, RT1011_CLK_2, + RT1011_FS_SYS_PRE_MASK, RT1011_FS_SYS_PRE_BCLK); + return 0; + } + + switch (source) { + case RT1011_PLL2_S_MCLK: + snd_soc_component_update_bits(component, RT1011_CLK_2, + RT1011_PLL2_SRC_MASK, RT1011_PLL2_SRC_MCLK); + snd_soc_component_update_bits(component, RT1011_CLK_2, + RT1011_PLL1_SRC_MASK, RT1011_PLL1_SRC_PLL2); + snd_soc_component_update_bits(component, RT1011_CLK_DET, + RT1011_EN_MCLK_DET_MASK, RT1011_EN_MCLK_DET); + break; + case RT1011_PLL1_S_BCLK: + snd_soc_component_update_bits(component, RT1011_CLK_2, + RT1011_PLL1_SRC_MASK, RT1011_PLL1_SRC_BCLK); + break; + case RT1011_PLL2_S_RCCLK: + snd_soc_component_update_bits(component, RT1011_CLK_2, + RT1011_PLL2_SRC_MASK, RT1011_PLL2_SRC_RCCLK); + snd_soc_component_update_bits(component, RT1011_CLK_2, + RT1011_PLL1_SRC_MASK, RT1011_PLL1_SRC_PLL2); + break; + default: + dev_err(component->dev, "Unknown PLL Source %d\n", source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(component->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), + pll_code.n_code, pll_code.k_code); + + snd_soc_component_write(component, RT1011_PLL_1, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT1011_PLL1_QM_SFT | + pll_code.m_bp << RT1011_PLL1_BPM_SFT | pll_code.n_code); + snd_soc_component_write(component, RT1011_PLL_2, + pll_code.k_code); + + rt1011->pll_in = freq_in; + rt1011->pll_out = freq_out; + rt1011->pll_src = source; + + return 0; +} + +static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + unsigned int val = 0, tdm_en = 0; + + if (rx_mask || tx_mask) + tdm_en = RT1011_TDM_I2S_DOCK_EN_1; + + switch (slots) { + case 4: + val |= RT1011_I2S_TX_4CH; + val |= RT1011_I2S_RX_4CH; + break; + case 6: + val |= RT1011_I2S_TX_6CH; + val |= RT1011_I2S_RX_6CH; + break; + case 8: + val |= RT1011_I2S_TX_8CH; + val |= RT1011_I2S_RX_8CH; + break; + case 2: + break; + default: + return -EINVAL; + } + + switch (slot_width) { + case 20: + val |= RT1011_I2S_CH_TX_LEN_20B; + val |= RT1011_I2S_CH_RX_LEN_20B; + break; + case 24: + val |= RT1011_I2S_CH_TX_LEN_24B; + val |= RT1011_I2S_CH_RX_LEN_24B; + break; + case 32: + val |= RT1011_I2S_CH_TX_LEN_32B; + val |= RT1011_I2S_CH_RX_LEN_32B; + break; + case 16: + break; + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, RT1011_TDM1_SET_1, + RT1011_I2S_CH_TX_MASK | RT1011_I2S_CH_RX_MASK | + RT1011_I2S_CH_TX_LEN_MASK | RT1011_I2S_CH_RX_LEN_MASK, val); + snd_soc_component_update_bits(component, RT1011_TDM2_SET_1, + RT1011_I2S_CH_TX_MASK | RT1011_I2S_CH_RX_MASK | + RT1011_I2S_CH_TX_LEN_MASK | RT1011_I2S_CH_RX_LEN_MASK, val); + snd_soc_component_update_bits(component, RT1011_TDM1_SET_2, + RT1011_TDM_I2S_DOCK_EN_1_MASK, tdm_en); + snd_soc_component_update_bits(component, RT1011_TDM2_SET_2, + RT1011_TDM_I2S_DOCK_EN_2_MASK, tdm_en); + snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET, + RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG, + RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT); + + return 0; +} + +static int rt1011_probe(struct snd_soc_component *component) +{ + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + int i; + + rt1011->component = component; + + schedule_work(&rt1011->cali_work); + + rt1011->bq_drc_params = devm_kcalloc(component->dev, + RT1011_ADVMODE_NUM, sizeof(struct rt1011_bq_drc_params *), + GFP_KERNEL); + if (!rt1011->bq_drc_params) + return -ENOMEM; + + for (i = 0; i < RT1011_ADVMODE_NUM; i++) { + rt1011->bq_drc_params[i] = devm_kcalloc(component->dev, + RT1011_BQ_DRC_NUM, sizeof(struct rt1011_bq_drc_params), + GFP_KERNEL); + if (!rt1011->bq_drc_params[i]) + return -ENOMEM; + } + + return 0; +} + +static void rt1011_remove(struct snd_soc_component *component) +{ + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + + cancel_work_sync(&rt1011->cali_work); + rt1011_reset(rt1011->regmap); +} + +#ifdef CONFIG_PM +static int rt1011_suspend(struct snd_soc_component *component) +{ + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt1011->regmap, true); + regcache_mark_dirty(rt1011->regmap); + + return 0; +} + +static int rt1011_resume(struct snd_soc_component *component) +{ + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt1011->regmap, false); + regcache_sync(rt1011->regmap); + + return 0; +} +#else +#define rt1011_suspend NULL +#define rt1011_resume NULL +#endif + +static int rt1011_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + switch (level) { + case SND_SOC_BIAS_OFF: + snd_soc_component_write(component, + RT1011_SYSTEM_RESET_1, 0x0000); + snd_soc_component_write(component, + RT1011_SYSTEM_RESET_2, 0x0000); + snd_soc_component_write(component, + RT1011_SYSTEM_RESET_3, 0x0000); + snd_soc_component_write(component, + RT1011_SYSTEM_RESET_1, 0x003f); + snd_soc_component_write(component, + RT1011_SYSTEM_RESET_2, 0x7fd7); + snd_soc_component_write(component, + RT1011_SYSTEM_RESET_3, 0x770f); + break; + default: + break; + } + + return 0; +} + +#define RT1011_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT1011_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static const struct snd_soc_dai_ops rt1011_aif_dai_ops = { + .hw_params = rt1011_hw_params, + .set_fmt = rt1011_set_dai_fmt, + .set_tdm_slot = rt1011_set_tdm_slot, +}; + +static struct snd_soc_dai_driver rt1011_dai[] = { + { + .name = "rt1011-aif", + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT1011_STEREO_RATES, + .formats = RT1011_FORMATS, + }, + .ops = &rt1011_aif_dai_ops, + }, +}; + +static const struct snd_soc_component_driver soc_component_dev_rt1011 = { + .probe = rt1011_probe, + .remove = rt1011_remove, + .suspend = rt1011_suspend, + .resume = rt1011_resume, + .set_bias_level = rt1011_set_bias_level, + .controls = rt1011_snd_controls, + .num_controls = ARRAY_SIZE(rt1011_snd_controls), + .dapm_widgets = rt1011_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt1011_dapm_widgets), + .dapm_routes = rt1011_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt1011_dapm_routes), + .set_sysclk = rt1011_set_component_sysclk, + .set_pll = rt1011_set_component_pll, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct regmap_config rt1011_regmap = { + .reg_bits = 16, + .val_bits = 16, + .max_register = RT1011_MAX_REG + 1, + .volatile_reg = rt1011_volatile_register, + .readable_reg = rt1011_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt1011_reg, + .num_reg_defaults = ARRAY_SIZE(rt1011_reg), + .use_single_read = true, + .use_single_write = true, +}; + +#if defined(CONFIG_OF) +static const struct of_device_id rt1011_of_match[] = { + { .compatible = "realtek,rt1011", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt1011_of_match); +#endif + +#ifdef CONFIG_ACPI +static struct acpi_device_id rt1011_acpi_match[] = { + {"10EC1011", 0,}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, rt1011_acpi_match); +#endif + +static const struct i2c_device_id rt1011_i2c_id[] = { + { "rt1011", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt1011_i2c_id); + +static int rt1011_calibrate(struct rt1011_priv *rt1011, unsigned char cali_flag) +{ + unsigned int value, count = 0, r0[3]; + unsigned int chk_cnt = 50; /* DONT change this */ + unsigned int dc_offset; + unsigned int r0_integer, r0_factor, format; + struct device *dev = regmap_get_device(rt1011->regmap); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(rt1011->component); + int ret = 0; + + snd_soc_dapm_mutex_lock(dapm); + regcache_cache_bypass(rt1011->regmap, true); + + regmap_write(rt1011->regmap, RT1011_RESET, 0x0000); + regmap_write(rt1011->regmap, RT1011_SYSTEM_RESET_3, 0x740f); + regmap_write(rt1011->regmap, RT1011_SYSTEM_RESET_3, 0x770f); + + /* RC clock */ + regmap_write(rt1011->regmap, RT1011_CLK_2, 0x9400); + regmap_write(rt1011->regmap, RT1011_PLL_1, 0x0800); + regmap_write(rt1011->regmap, RT1011_PLL_2, 0x0020); + regmap_write(rt1011->regmap, RT1011_CLK_DET, 0x0800); + + /* ADC/DAC setting */ + regmap_write(rt1011->regmap, RT1011_ADC_SET_5, 0x0a20); + regmap_write(rt1011->regmap, RT1011_DAC_SET_2, 0xe232); + regmap_write(rt1011->regmap, RT1011_ADC_SET_1, 0x2925); + regmap_write(rt1011->regmap, RT1011_ADC_SET_4, 0xc000); + + /* DC detection */ + regmap_write(rt1011->regmap, RT1011_SPK_PRO_DC_DET_1, 0xb00c); + regmap_write(rt1011->regmap, RT1011_SPK_PRO_DC_DET_2, 0xcccc); + + /* Power */ + regmap_write(rt1011->regmap, RT1011_POWER_1, 0xe0e0); + regmap_write(rt1011->regmap, RT1011_POWER_3, 0x5003); + regmap_write(rt1011->regmap, RT1011_POWER_9, 0xa860); + regmap_write(rt1011->regmap, RT1011_DAC_SET_2, 0xa032); + + /* POW_PLL / POW_BG / POW_BG_MBIAS_LV / POW_V/I */ + regmap_write(rt1011->regmap, RT1011_POWER_2, 0x0007); + regmap_write(rt1011->regmap, RT1011_POWER_3, 0x5ff7); + regmap_write(rt1011->regmap, RT1011_A_TEMP_SEN, 0x7f44); + regmap_write(rt1011->regmap, RT1011_A_TIMING_1, 0x4054); + regmap_write(rt1011->regmap, RT1011_BAT_GAIN_1, 0x309c); + + /* DC offset from EFUSE */ + regmap_write(rt1011->regmap, RT1011_DC_CALIB_CLASSD_3, 0xcb00); + regmap_write(rt1011->regmap, RT1011_BOOST_CON_1, 0xe080); + regmap_write(rt1011->regmap, RT1011_POWER_4, 0x16f2); + regmap_write(rt1011->regmap, RT1011_POWER_6, 0x36ad); + + /* mixer */ + regmap_write(rt1011->regmap, RT1011_MIXER_1, 0x3f1d); + + /* EFUSE read */ + regmap_write(rt1011->regmap, RT1011_EFUSE_CONTROL_1, 0x0d0a); + msleep(30); + + regmap_read(rt1011->regmap, RT1011_EFUSE_ADC_OFFSET_18_16, &value); + dc_offset = value << 16; + regmap_read(rt1011->regmap, RT1011_EFUSE_ADC_OFFSET_15_0, &value); + dc_offset |= (value & 0xffff); + dev_info(dev, "ADC offset=0x%x\n", dc_offset); + regmap_read(rt1011->regmap, RT1011_EFUSE_DAC_OFFSET_G0_20_16, &value); + dc_offset = value << 16; + regmap_read(rt1011->regmap, RT1011_EFUSE_DAC_OFFSET_G0_15_0, &value); + dc_offset |= (value & 0xffff); + dev_info(dev, "Gain0 offset=0x%x\n", dc_offset); + regmap_read(rt1011->regmap, RT1011_EFUSE_DAC_OFFSET_G1_20_16, &value); + dc_offset = value << 16; + regmap_read(rt1011->regmap, RT1011_EFUSE_DAC_OFFSET_G1_15_0, &value); + dc_offset |= (value & 0xffff); + dev_info(dev, "Gain1 offset=0x%x\n", dc_offset); + + + if (cali_flag) { + /* Class D on */ + regmap_write(rt1011->regmap, RT1011_CLASS_D_POS, 0x010e); + regmap_write(rt1011->regmap, + RT1011_CLASSD_INTERNAL_SET_1, 0x1701); + + /* STP enable */ + regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_0, 0x8000); + regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_7, 0xf000); + regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_4, 0x4040); + regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_0, 0xc000); + regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_6, 0x07c2); + + r0[0] = r0[1] = r0[2] = count = 0; + while (count < chk_cnt) { + msleep(100); + regmap_read(rt1011->regmap, + RT1011_INIT_RECIPROCAL_SYN_24_16, &value); + r0[count%3] = value << 16; + regmap_read(rt1011->regmap, + RT1011_INIT_RECIPROCAL_SYN_15_0, &value); + r0[count%3] |= value; + + if (r0[count%3] == 0) + continue; + + count++; + + if (r0[0] == r0[1] && r0[1] == r0[2]) + break; + } + if (count > chk_cnt) { + dev_err(dev, "Calibrate R0 Failure\n"); + ret = -EAGAIN; + } else { + format = 2147483648; /* 2^24 * 128 */ + r0_integer = format / r0[0] / 128; + r0_factor = ((format / r0[0] * 100) / 128) + - (r0_integer * 100); + rt1011->r0_reg = r0[0]; + dev_info(dev, "r0 resistance about %d.%02d ohm, reg=0x%X\n", + r0_integer, r0_factor, r0[0]); + } + } + + /* depop */ + regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_0, 0x0000); + msleep(400); + regmap_write(rt1011->regmap, RT1011_POWER_9, 0xa840); + regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_6, 0x0702); + regmap_write(rt1011->regmap, RT1011_MIXER_1, 0xffdd); + regmap_write(rt1011->regmap, RT1011_CLASSD_INTERNAL_SET_1, 0x0701); + regmap_write(rt1011->regmap, RT1011_DAC_SET_3, 0xe004); + regmap_write(rt1011->regmap, RT1011_A_TEMP_SEN, 0x7f40); + regmap_write(rt1011->regmap, RT1011_POWER_1, 0x0000); + regmap_write(rt1011->regmap, RT1011_POWER_2, 0x0000); + regmap_write(rt1011->regmap, RT1011_POWER_3, 0x0002); + regmap_write(rt1011->regmap, RT1011_POWER_4, 0x00f2); + + regmap_write(rt1011->regmap, RT1011_RESET, 0x0000); + + if (cali_flag) { + if (count <= chk_cnt) { + regmap_write(rt1011->regmap, + RT1011_INIT_RECIPROCAL_REG_24_16, + ((r0[0]>>16) & 0x1ff)); + regmap_write(rt1011->regmap, + RT1011_INIT_RECIPROCAL_REG_15_0, + (r0[0] & 0xffff)); + regmap_write(rt1011->regmap, + RT1011_SPK_TEMP_PROTECT_4, 0x4080); + } + } + + regcache_cache_bypass(rt1011->regmap, false); + regcache_mark_dirty(rt1011->regmap); + regcache_sync(rt1011->regmap); + snd_soc_dapm_mutex_unlock(dapm); + + return ret; +} + +static void rt1011_calibration_work(struct work_struct *work) +{ + struct rt1011_priv *rt1011 = + container_of(work, struct rt1011_priv, cali_work); + struct snd_soc_component *component = rt1011->component; + + rt1011_calibrate(rt1011, 1); + + /* initial */ + rt1011_reg_init(component); +} + +static int rt1011_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt1011_priv *rt1011; + int ret; + unsigned int val; + + rt1011 = devm_kzalloc(&i2c->dev, sizeof(struct rt1011_priv), + GFP_KERNEL); + if (rt1011 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt1011); + + rt1011->regmap = devm_regmap_init_i2c(i2c, &rt1011_regmap); + if (IS_ERR(rt1011->regmap)) { + ret = PTR_ERR(rt1011->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + regmap_read(rt1011->regmap, RT1011_DEVICE_ID, &val); + if (val != RT1011_DEVICE_ID_NUM) { + dev_err(&i2c->dev, + "Device with ID register %x is not rt1011\n", val); + return -ENODEV; + } + + INIT_WORK(&rt1011->cali_work, rt1011_calibration_work); + + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_rt1011, + rt1011_dai, ARRAY_SIZE(rt1011_dai)); + +} + +static void rt1011_i2c_shutdown(struct i2c_client *client) +{ + struct rt1011_priv *rt1011 = i2c_get_clientdata(client); + + rt1011_reset(rt1011->regmap); +} + + +static struct i2c_driver rt1011_i2c_driver = { + .driver = { + .name = "rt1011", + .of_match_table = of_match_ptr(rt1011_of_match), + .acpi_match_table = ACPI_PTR(rt1011_acpi_match) + }, + .probe = rt1011_i2c_probe, + .shutdown = rt1011_i2c_shutdown, + .id_table = rt1011_i2c_id, +}; +module_i2c_driver(rt1011_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT1011 amplifier driver"); +MODULE_AUTHOR("Shuming Fan "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt1011.h b/sound/soc/codecs/rt1011.h new file mode 100644 index 000000000000..98a38800c4df --- /dev/null +++ b/sound/soc/codecs/rt1011.h @@ -0,0 +1,672 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * rt1011.h -- RT1011 ALSA SoC amplifier component driver header + * + * Copyright(c) 2019 Realtek Semiconductor Corp. + */ + +#ifndef _RT1011_H_ +#define _RT1011_H_ + +#define RT1011_DEVICE_ID_NUM 0x1011 + +#define RT1011_RESET 0x0000 +#define RT1011_CLK_1 0x0002 +#define RT1011_CLK_2 0x0004 +#define RT1011_CLK_3 0x0006 +#define RT1011_CLK_4 0x0008 +#define RT1011_PLL_1 0x000a +#define RT1011_PLL_2 0x000c +#define RT1011_SRC_1 0x000e +#define RT1011_SRC_2 0x0010 +#define RT1011_SRC_3 0x0012 +#define RT1011_CLK_DET 0x0020 +#define RT1011_SIL_DET 0x0022 +#define RT1011_PRIV_INDEX 0x006a +#define RT1011_PRIV_DATA 0x006c +#define RT1011_CUSTOMER_ID 0x0076 +#define RT1011_FM_VER 0x0078 +#define RT1011_VERSION_ID 0x007a +#define RT1011_VENDOR_ID 0x007c +#define RT1011_DEVICE_ID 0x007d +#define RT1011_DUM_RW_0 0x00f0 +#define RT1011_DUM_YUN 0x00f2 +#define RT1011_DUM_RW_1 0x00f3 +#define RT1011_DUM_RO 0x00f4 +#define RT1011_MAN_I2C_DEV 0x0100 +#define RT1011_DAC_SET_1 0x0102 +#define RT1011_DAC_SET_2 0x0104 +#define RT1011_DAC_SET_3 0x0106 +#define RT1011_ADC_SET 0x0107 +#define RT1011_ADC_SET_1 0x0108 +#define RT1011_ADC_SET_2 0x010a +#define RT1011_ADC_SET_3 0x010c +#define RT1011_ADC_SET_4 0x010e +#define RT1011_ADC_SET_5 0x0110 +#define RT1011_TDM_TOTAL_SET 0x0111 +#define RT1011_TDM1_SET_TCON 0x0112 +#define RT1011_TDM1_SET_1 0x0114 +#define RT1011_TDM1_SET_2 0x0116 +#define RT1011_TDM1_SET_3 0x0118 +#define RT1011_TDM1_SET_4 0x011a +#define RT1011_TDM1_SET_5 0x011c +#define RT1011_TDM2_SET_1 0x011e +#define RT1011_TDM2_SET_2 0x0120 +#define RT1011_TDM2_SET_3 0x0122 +#define RT1011_TDM2_SET_4 0x0124 +#define RT1011_TDM2_SET_5 0x0126 +#define RT1011_PWM_CAL 0x0200 +#define RT1011_MIXER_1 0x0300 +#define RT1011_MIXER_2 0x0302 +#define RT1011_ADRC_LIMIT 0x0310 +#define RT1011_A_PRO 0x0311 +#define RT1011_A_TIMING_1 0x0313 +#define RT1011_A_TIMING_2 0x0314 +#define RT1011_A_TEMP_SEN 0x0316 +#define RT1011_SPK_VOL_DET_1 0x0319 +#define RT1011_SPK_VOL_DET_2 0x031a +#define RT1011_SPK_VOL_TEST_OUT 0x031b +#define RT1011_VBAT_VOL_DET_1 0x031c +#define RT1011_VBAT_VOL_DET_2 0x031d +#define RT1011_VBAT_TEST_OUT_1 0x031e +#define RT1011_VBAT_TEST_OUT_2 0x031f +#define RT1011_VBAT_PROTECTION 0x0320 +#define RT1011_VBAT_DET 0x0321 +#define RT1011_POWER_1 0x0322 +#define RT1011_POWER_2 0x0324 +#define RT1011_POWER_3 0x0326 +#define RT1011_POWER_4 0x0328 +#define RT1011_POWER_5 0x0329 +#define RT1011_POWER_6 0x032a +#define RT1011_POWER_7 0x032b +#define RT1011_POWER_8 0x032c +#define RT1011_POWER_9 0x032d +#define RT1011_CLASS_D_POS 0x032e +#define RT1011_BOOST_CON_1 0x0330 +#define RT1011_BOOST_CON_2 0x0332 +#define RT1011_ANALOG_CTRL 0x0334 +#define RT1011_POWER_SEQ 0x0340 +#define RT1011_SHORT_CIRCUIT_DET_1 0x0508 +#define RT1011_SHORT_CIRCUIT_DET_2 0x050a +#define RT1011_SPK_TEMP_PROTECT_0 0x050c +#define RT1011_SPK_TEMP_PROTECT_1 0x050d +#define RT1011_SPK_TEMP_PROTECT_2 0x050e +#define RT1011_SPK_TEMP_PROTECT_3 0x050f +#define RT1011_SPK_TEMP_PROTECT_4 0x0510 +#define RT1011_SPK_TEMP_PROTECT_5 0x0511 +#define RT1011_SPK_TEMP_PROTECT_6 0x0512 +#define RT1011_SPK_TEMP_PROTECT_7 0x0516 +#define RT1011_SPK_TEMP_PROTECT_8 0x0517 +#define RT1011_SPK_TEMP_PROTECT_9 0x0518 +#define RT1011_SPK_PRO_DC_DET_1 0x0519 +#define RT1011_SPK_PRO_DC_DET_2 0x051a +#define RT1011_SPK_PRO_DC_DET_3 0x051b +#define RT1011_SPK_PRO_DC_DET_4 0x051c +#define RT1011_SPK_PRO_DC_DET_5 0x051d +#define RT1011_SPK_PRO_DC_DET_6 0x051e +#define RT1011_SPK_PRO_DC_DET_7 0x051f +#define RT1011_SPK_PRO_DC_DET_8 0x0520 +#define RT1011_SPL_1 0x0521 +#define RT1011_SPL_2 0x0522 +#define RT1011_SPL_3 0x0524 +#define RT1011_SPL_4 0x0526 +#define RT1011_THER_FOLD_BACK_1 0x0528 +#define RT1011_THER_FOLD_BACK_2 0x052a +#define RT1011_EXCUR_PROTECT_1 0x0530 +#define RT1011_EXCUR_PROTECT_2 0x0532 +#define RT1011_EXCUR_PROTECT_3 0x0534 +#define RT1011_EXCUR_PROTECT_4 0x0535 +#define RT1011_BAT_GAIN_1 0x0536 +#define RT1011_BAT_GAIN_2 0x0538 +#define RT1011_BAT_GAIN_3 0x053a +#define RT1011_BAT_GAIN_4 0x053c +#define RT1011_BAT_GAIN_5 0x053d +#define RT1011_BAT_GAIN_6 0x053e +#define RT1011_BAT_GAIN_7 0x053f +#define RT1011_BAT_GAIN_8 0x0540 +#define RT1011_BAT_GAIN_9 0x0541 +#define RT1011_BAT_GAIN_10 0x0542 +#define RT1011_BAT_GAIN_11 0x0543 +#define RT1011_BAT_RT_THMAX_1 0x0544 +#define RT1011_BAT_RT_THMAX_2 0x0545 +#define RT1011_BAT_RT_THMAX_3 0x0546 +#define RT1011_BAT_RT_THMAX_4 0x0547 +#define RT1011_BAT_RT_THMAX_5 0x0548 +#define RT1011_BAT_RT_THMAX_6 0x0549 +#define RT1011_BAT_RT_THMAX_7 0x054a +#define RT1011_BAT_RT_THMAX_8 0x054b +#define RT1011_BAT_RT_THMAX_9 0x054c +#define RT1011_BAT_RT_THMAX_10 0x054d +#define RT1011_BAT_RT_THMAX_11 0x054e +#define RT1011_BAT_RT_THMAX_12 0x054f +#define RT1011_SPREAD_SPECTURM 0x0568 +#define RT1011_PRO_GAIN_MODE 0x056a +#define RT1011_RT_DRC_CROSS 0x0600 +#define RT1011_RT_DRC_HB_1 0x0611 +#define RT1011_RT_DRC_HB_2 0x0612 +#define RT1011_RT_DRC_HB_3 0x0613 +#define RT1011_RT_DRC_HB_4 0x0614 +#define RT1011_RT_DRC_HB_5 0x0615 +#define RT1011_RT_DRC_HB_6 0x0616 +#define RT1011_RT_DRC_HB_7 0x0617 +#define RT1011_RT_DRC_HB_8 0x0618 +#define RT1011_RT_DRC_BB_1 0x0621 +#define RT1011_RT_DRC_BB_2 0x0622 +#define RT1011_RT_DRC_BB_3 0x0623 +#define RT1011_RT_DRC_BB_4 0x0624 +#define RT1011_RT_DRC_BB_5 0x0625 +#define RT1011_RT_DRC_BB_6 0x0626 +#define RT1011_RT_DRC_BB_7 0x0627 +#define RT1011_RT_DRC_BB_8 0x0628 +#define RT1011_RT_DRC_POS_1 0x0631 +#define RT1011_RT_DRC_POS_2 0x0632 +#define RT1011_RT_DRC_POS_3 0x0633 +#define RT1011_RT_DRC_POS_4 0x0634 +#define RT1011_RT_DRC_POS_5 0x0635 +#define RT1011_RT_DRC_POS_6 0x0636 +#define RT1011_RT_DRC_POS_7 0x0637 +#define RT1011_RT_DRC_POS_8 0x0638 +#define RT1011_CROSS_BQ_SET_1 0x0702 +#define RT1011_CROSS_BQ_SET_2 0x0704 +#define RT1011_BQ_SET_0 0x0706 +#define RT1011_BQ_SET_1 0x0708 +#define RT1011_BQ_SET_2 0x070a +#define RT1011_BQ_PRE_GAIN_28_16 0x0710 +#define RT1011_BQ_PRE_GAIN_15_0 0x0711 +#define RT1011_BQ_POST_GAIN_28_16 0x0712 +#define RT1011_BQ_POST_GAIN_15_0 0x0713 + +#define RT1011_BQ_H0_28_16 0x0720 +#define RT1011_BQ_A2_15_0 0x0729 +#define RT1011_BQ_1_H0_28_16 0x0730 +#define RT1011_BQ_1_A2_15_0 0x0739 +#define RT1011_BQ_2_H0_28_16 0x0740 +#define RT1011_BQ_2_A2_15_0 0x0749 +#define RT1011_BQ_3_H0_28_16 0x0750 +#define RT1011_BQ_3_A2_15_0 0x0759 +#define RT1011_BQ_4_H0_28_16 0x0760 +#define RT1011_BQ_4_A2_15_0 0x0769 +#define RT1011_BQ_5_H0_28_16 0x0770 +#define RT1011_BQ_5_A2_15_0 0x0779 +#define RT1011_BQ_6_H0_28_16 0x0780 +#define RT1011_BQ_6_A2_15_0 0x0789 +#define RT1011_BQ_7_H0_28_16 0x0790 +#define RT1011_BQ_7_A2_15_0 0x0799 +#define RT1011_BQ_8_H0_28_16 0x07a0 +#define RT1011_BQ_8_A2_15_0 0x07a9 +#define RT1011_BQ_9_H0_28_16 0x07b0 +#define RT1011_BQ_9_A2_15_0 0x07b9 +#define RT1011_BQ_10_H0_28_16 0x07c0 +#define RT1011_BQ_10_A2_15_0 0x07c9 +#define RT1011_TEST_PAD_STATUS 0x1000 +#define RT1011_SYSTEM_RESET_1 0x1007 +#define RT1011_SYSTEM_RESET_2 0x1008 +#define RT1011_SYSTEM_RESET_3 0x1009 +#define RT1011_ADCDAT_OUT_SOURCE 0x100D +#define RT1011_PLL_INTERNAL_SET 0x1010 +#define RT1011_TEST_OUT_1 0x1020 +#define RT1011_TEST_OUT_3 0x1024 +#define RT1011_DC_CALIB_CLASSD_1 0x1200 +#define RT1011_DC_CALIB_CLASSD_2 0x1202 +#define RT1011_DC_CALIB_CLASSD_3 0x1204 +#define RT1011_DC_CALIB_CLASSD_5 0x1208 +#define RT1011_DC_CALIB_CLASSD_6 0x120a +#define RT1011_DC_CALIB_CLASSD_7 0x120c +#define RT1011_DC_CALIB_CLASSD_8 0x120e +#define RT1011_DC_CALIB_CLASSD_10 0x1212 +#define RT1011_CLASSD_INTERNAL_SET_1 0x1300 +#define RT1011_CLASSD_INTERNAL_SET_3 0x1304 +#define RT1011_CLASSD_INTERNAL_SET_8 0x130c +#define RT1011_VREF_LV_1 0x131a +#define RT1011_SMART_BOOST_TIMING_1 0x1322 +#define RT1011_SMART_BOOST_TIMING_36 0x1349 +#define RT1011_SINE_GEN_REG_1 0x1500 +#define RT1011_SINE_GEN_REG_2 0x1502 +#define RT1011_SINE_GEN_REG_3 0x1504 +#define RT1011_STP_INITIAL_RS_TEMP 0x1510 +#define RT1011_STP_CALIB_RS_TEMP 0x152a +#define RT1011_INIT_RECIPROCAL_REG_24_16 0x1538 +#define RT1011_INIT_RECIPROCAL_REG_15_0 0x1539 +#define RT1011_STP_ALPHA_RECIPROCAL_MSB 0x153e +#define RT1011_SPK_RESISTANCE_1 0x1544 +#define RT1011_SPK_RESISTANCE_2 0x1546 +#define RT1011_SPK_THERMAL 0x1548 +#define RT1011_STP_OTP_TH 0x1552 +#define RT1011_ALC_BK_GAIN_O 0x1554 +#define RT1011_ALC_BK_GAIN_O_PRE 0x1556 +#define RT1011_SPK_DC_O_23_16 0x155a +#define RT1011_SPK_DC_O_15_0 0x155c +#define RT1011_INIT_RECIPROCAL_SYN_24_16 0x1560 +#define RT1011_INIT_RECIPROCAL_SYN_15_0 0x1562 +#define RT1011_STP_BQ_1_A1_L_28_16 0x1570 +#define RT1011_STP_BQ_1_H0_R_15_0 0x1583 +#define RT1011_STP_BQ_2_A1_L_28_16 0x1590 +#define RT1011_SPK_EXCURSION_23_16 0x15be +#define RT1011_SPK_EXCURSION_15_0 0x15bf +#define RT1011_SEP_MAIN_OUT_23_16 0x15c0 +#define RT1011_SEP_MAIN_OUT_15_0 0x15c1 +#define RT1011_SEP_RE_REG_15_0 0x15f9 +#define RT1011_DRC_CF_PARAMS_1 0x1600 +#define RT1011_DRC_CF_PARAMS_12 0x160b +#define RT1011_ALC_DRC_HB_INTERNAL_1 0x1611 +#define RT1011_ALC_DRC_HB_INTERNAL_5 0x1615 +#define RT1011_ALC_DRC_HB_INTERNAL_6 0x1616 +#define RT1011_ALC_DRC_HB_INTERNAL_7 0x1617 +#define RT1011_ALC_DRC_BB_INTERNAL_1 0x1621 +#define RT1011_ALC_DRC_BB_INTERNAL_5 0x1625 +#define RT1011_ALC_DRC_BB_INTERNAL_6 0x1626 +#define RT1011_ALC_DRC_BB_INTERNAL_7 0x1627 +#define RT1011_ALC_DRC_POS_INTERNAL_1 0x1631 +#define RT1011_ALC_DRC_POS_INTERNAL_5 0x1635 +#define RT1011_ALC_DRC_POS_INTERNAL_6 0x1636 +#define RT1011_ALC_DRC_POS_INTERNAL_7 0x1637 +#define RT1011_ALC_DRC_POS_INTERNAL_8 0x1638 +#define RT1011_ALC_DRC_POS_INTERNAL_9 0x163a +#define RT1011_ALC_DRC_POS_INTERNAL_10 0x163c +#define RT1011_ALC_DRC_POS_INTERNAL_11 0x163e +#define RT1011_BQ_1_PARAMS_CHECK_5 0x1648 +#define RT1011_BQ_2_PARAMS_CHECK_1 0x1650 +#define RT1011_BQ_2_PARAMS_CHECK_5 0x1658 +#define RT1011_BQ_3_PARAMS_CHECK_1 0x1660 +#define RT1011_BQ_3_PARAMS_CHECK_5 0x1668 +#define RT1011_BQ_4_PARAMS_CHECK_1 0x1670 +#define RT1011_BQ_4_PARAMS_CHECK_5 0x1678 +#define RT1011_BQ_5_PARAMS_CHECK_1 0x1680 +#define RT1011_BQ_5_PARAMS_CHECK_5 0x1688 +#define RT1011_BQ_6_PARAMS_CHECK_1 0x1690 +#define RT1011_BQ_6_PARAMS_CHECK_5 0x1698 +#define RT1011_BQ_7_PARAMS_CHECK_1 0x1700 +#define RT1011_BQ_7_PARAMS_CHECK_5 0x1708 +#define RT1011_BQ_8_PARAMS_CHECK_1 0x1710 +#define RT1011_BQ_8_PARAMS_CHECK_5 0x1718 +#define RT1011_BQ_9_PARAMS_CHECK_1 0x1720 +#define RT1011_BQ_9_PARAMS_CHECK_5 0x1728 +#define RT1011_BQ_10_PARAMS_CHECK_1 0x1730 +#define RT1011_BQ_10_PARAMS_CHECK_5 0x1738 +#define RT1011_IRQ_1 0x173a +#define RT1011_PART_NUMBER_EFUSE 0x173e +#define RT1011_EFUSE_CONTROL_1 0x17bb +#define RT1011_EFUSE_CONTROL_2 0x17bd +#define RT1011_EFUSE_MATCH_DONE 0x17cb +#define RT1011_EFUSE_ADC_OFFSET_18_16 0x17e5 +#define RT1011_EFUSE_ADC_OFFSET_15_0 0x17e7 +#define RT1011_EFUSE_DAC_OFFSET_G0_20_16 0x17e9 +#define RT1011_EFUSE_DAC_OFFSET_G0_15_0 0x17eb +#define RT1011_EFUSE_DAC_OFFSET_G1_20_16 0x17ed +#define RT1011_EFUSE_DAC_OFFSET_G1_15_0 0x17ef +#define RT1011_EFUSE_READ_R0_3_15_0 0x1803 +#define RT1011_MAX_REG 0x1803 +#define RT1011_REG_DISP_LEN 23 + + +/* CLOCK-2 (0x0004) */ +#define RT1011_FS_SYS_PRE_MASK (0x3 << 14) +#define RT1011_FS_SYS_PRE_SFT 14 +#define RT1011_FS_SYS_PRE_MCLK (0x0 << 14) +#define RT1011_FS_SYS_PRE_BCLK (0x1 << 14) +#define RT1011_FS_SYS_PRE_PLL1 (0x2 << 14) +#define RT1011_FS_SYS_PRE_RCCLK (0x3 << 14) +#define RT1011_PLL1_SRC_MASK (0x1 << 13) +#define RT1011_PLL1_SRC_SFT 13 +#define RT1011_PLL1_SRC_PLL2 (0x0 << 13) +#define RT1011_PLL1_SRC_BCLK (0x1 << 13) +#define RT1011_PLL2_SRC_MASK (0x1 << 12) +#define RT1011_PLL2_SRC_SFT 12 +#define RT1011_PLL2_SRC_MCLK (0x0 << 12) +#define RT1011_PLL2_SRC_RCCLK (0x1 << 12) +#define RT1011_PLL2_SRC_DIV_MASK (0x3 << 10) +#define RT1011_PLL2_SRC_DIV_SFT 10 +#define RT1011_SRCIN_DIV_MASK (0x3 << 8) +#define RT1011_SRCIN_DIV_SFT 8 +#define RT1011_FS_SYS_DIV_MASK (0x7 << 4) +#define RT1011_FS_SYS_DIV_SFT 4 + +/* PLL-1 (0x000a) */ +#define RT1011_PLL1_QM_MASK (0xf << 12) +#define RT1011_PLL1_QM_SFT 12 +#define RT1011_PLL1_BPM_MASK (0x1 << 11) +#define RT1011_PLL1_BPM_SFT 11 +#define RT1011_PLL1_BPM (0x1 << 11) +#define RT1011_PLL1_QN_MASK (0x1ff << 0) +#define RT1011_PLL1_QN_SFT 0 + +/* PLL-2 (0x000c) */ +#define RT1011_PLL2_BPK_MASK (0x1 << 5) +#define RT1011_PLL2_BPK_SFT 5 +#define RT1011_PLL2_BPK (0x1 << 5) +#define RT1011_PLL2_QK_MASK (0x1f << 0) +#define RT1011_PLL2_QK_SFT 0 + +/* Clock Detect (0x0020) */ +#define RT1011_EN_MCLK_DET_MASK (0x1 << 15) +#define RT1011_EN_MCLK_DET_SFT 15 +#define RT1011_EN_MCLK_DET (0x1 << 15) + +/* DAC Setting-2 (0x0104) */ +#define RT1011_EN_CKGEN_DAC_MASK (0x1 << 13) +#define RT1011_EN_CKGEN_DAC_SFT 13 +#define RT1011_EN_CKGEN_DAC (0x1 << 13) + +/* DAC Setting-3 (0x0106) */ +#define RT1011_DA_MUTE_EN_MASK (0x1 << 15) +#define RT1011_DA_MUTE_EN_SFT 15 + +/* ADC Setting-5 (0x0110) */ +#define RT1011_AD_EN_CKGEN_ADC_MASK (0x1 << 9) +#define RT1011_AD_EN_CKGEN_ADC_SFT 9 +#define RT1011_AD_EN_CKGEN_ADC (0x1 << 9) + +/* TDM Total Setting (0x0111) */ +#define RT1011_I2S_TDM_MS_MASK (0x1 << 14) +#define RT1011_I2S_TDM_MS_SFT 14 +#define RT1011_I2S_TDM_MS_S (0x0 << 14) +#define RT1011_I2S_TDM_MS_M (0x1 << 14) +#define RT1011_I2S_TX_DL_MASK (0x7 << 8) +#define RT1011_I2S_TX_DL_SFT 8 +#define RT1011_I2S_TX_DL_16B (0x0 << 8) +#define RT1011_I2S_TX_DL_20B (0x1 << 8) +#define RT1011_I2S_TX_DL_24B (0x2 << 8) +#define RT1011_I2S_TX_DL_32B (0x3 << 8) +#define RT1011_I2S_TX_DL_8B (0x4 << 8) +#define RT1011_I2S_RX_DL_MASK (0x7 << 5) +#define RT1011_I2S_RX_DL_SFT 5 +#define RT1011_I2S_RX_DL_16B (0x0 << 5) +#define RT1011_I2S_RX_DL_20B (0x1 << 5) +#define RT1011_I2S_RX_DL_24B (0x2 << 5) +#define RT1011_I2S_RX_DL_32B (0x3 << 5) +#define RT1011_I2S_RX_DL_8B (0x4 << 5) +#define RT1011_ADCDAT1_PIN_CONFIG (0x1 << 4) +#define RT1011_ADCDAT1_OUTPUT (0x0 << 4) +#define RT1011_ADCDAT1_INPUT (0x1 << 4) +#define RT1011_ADCDAT2_PIN_CONFIG (0x1 << 3) +#define RT1011_ADCDAT2_OUTPUT (0x0 << 3) +#define RT1011_ADCDAT2_INPUT (0x1 << 3) +#define RT1011_I2S_TDM_DF_MASK (0x7 << 0) +#define RT1011_I2S_TDM_DF_SFT 0 +#define RT1011_I2S_TDM_DF_I2S (0x0) +#define RT1011_I2S_TDM_DF_LEFT (0x1) +#define RT1011_I2S_TDM_DF_PCM_A (0x2) +#define RT1011_I2S_TDM_DF_PCM_B (0x3) +#define RT1011_I2S_TDM_DF_PCM_A_N (0x6) +#define RT1011_I2S_TDM_DF_PCM_B_N (0x7) + +/* TDM_tcon Setting (0x0112) */ +#define RT1011_TCON_DF_MASK (0x7 << 13) +#define RT1011_TCON_DF_SFT 13 +#define RT1011_TCON_DF_I2S (0x0 << 13) +#define RT1011_TCON_DF_LEFT (0x1 << 13) +#define RT1011_TCON_DF_PCM_A (0x2 << 13) +#define RT1011_TCON_DF_PCM_B (0x3 << 13) +#define RT1011_TCON_DF_PCM_A_N (0x6 << 13) +#define RT1011_TCON_DF_PCM_B_N (0x7 << 13) +#define RT1011_TCON_BCLK_SEL_MASK (0x3 << 10) +#define RT1011_TCON_BCLK_SEL_SFT 10 +#define RT1011_TCON_BCLK_SEL_32FS (0x0 << 10) +#define RT1011_TCON_BCLK_SEL_64FS (0x1 << 10) +#define RT1011_TCON_BCLK_SEL_128FS (0x2 << 10) +#define RT1011_TCON_BCLK_SEL_256FS (0x3 << 10) +#define RT1011_TCON_CH_LEN_MASK (0x3 << 5) +#define RT1011_TCON_CH_LEN_SFT 5 +#define RT1011_TCON_CH_LEN_16B (0x0 << 5) +#define RT1011_TCON_CH_LEN_20B (0x1 << 5) +#define RT1011_TCON_CH_LEN_24B (0x2 << 5) +#define RT1011_TCON_CH_LEN_32B (0x3 << 5) +#define RT1011_TCON_BCLK_MST_MASK (0x1 << 4) +#define RT1011_TCON_BCLK_MST_SFT 4 +#define RT1011_TCON_BCLK_MST_INV (0x1 << 4) + +/* TDM1 Setting-1 (0x0114) */ +#define RT1011_TDM_INV_BCLK_MASK (0x1 << 15) +#define RT1011_TDM_INV_BCLK_SFT 15 +#define RT1011_TDM_INV_BCLK (0x1 << 15) +#define RT1011_I2S_CH_TX_MASK (0x3 << 10) +#define RT1011_I2S_CH_TX_SFT 10 +#define RT1011_I2S_TX_2CH (0x0 << 10) +#define RT1011_I2S_TX_4CH (0x1 << 10) +#define RT1011_I2S_TX_6CH (0x2 << 10) +#define RT1011_I2S_TX_8CH (0x3 << 10) +#define RT1011_I2S_CH_RX_MASK (0x3 << 8) +#define RT1011_I2S_CH_RX_SFT 8 +#define RT1011_I2S_RX_2CH (0x0 << 8) +#define RT1011_I2S_RX_4CH (0x1 << 8) +#define RT1011_I2S_RX_6CH (0x2 << 8) +#define RT1011_I2S_RX_8CH (0x3 << 8) +#define RT1011_I2S_LR_CH_SEL_MASK (0x1 << 7) +#define RT1011_I2S_LR_CH_SEL_SFT 7 +#define RT1011_I2S_LEFT_CH_SEL (0x0 << 7) +#define RT1011_I2S_RIGHT_CH_SEL (0x1 << 7) +#define RT1011_I2S_CH_TX_LEN_MASK (0x7 << 4) +#define RT1011_I2S_CH_TX_LEN_SFT 4 +#define RT1011_I2S_CH_TX_LEN_16B (0x0 << 4) +#define RT1011_I2S_CH_TX_LEN_20B (0x1 << 4) +#define RT1011_I2S_CH_TX_LEN_24B (0x2 << 4) +#define RT1011_I2S_CH_TX_LEN_32B (0x3 << 4) +#define RT1011_I2S_CH_TX_LEN_8B (0x4 << 4) +#define RT1011_I2S_CH_RX_LEN_MASK (0x7 << 0) +#define RT1011_I2S_CH_RX_LEN_SFT 0 +#define RT1011_I2S_CH_RX_LEN_16B (0x0 << 0) +#define RT1011_I2S_CH_RX_LEN_20B (0x1 << 0) +#define RT1011_I2S_CH_RX_LEN_24B (0x2 << 0) +#define RT1011_I2S_CH_RX_LEN_32B (0x3 << 0) +#define RT1011_I2S_CH_RX_LEN_8B (0x4 << 0) + +/* TDM1 Setting-2 (0x0116) */ +#define RT1011_TDM_I2S_DOCK_ADCDAT_LEN_1_MASK (0x7 << 13) +#define RT1011_TDM_I2S_DOCK_ADCDAT_2CH (0x1 << 13) +#define RT1011_TDM_I2S_DOCK_ADCDAT_4CH (0x3 << 13) +#define RT1011_TDM_I2S_DOCK_ADCDAT_6CH (0x5 << 13) +#define RT1011_TDM_I2S_DOCK_ADCDAT_8CH (0x7 << 13) +#define RT1011_TDM_I2S_DOCK_EN_1_MASK (0x1 << 3) +#define RT1011_TDM_I2S_DOCK_EN_1_SFT 3 +#define RT1011_TDM_I2S_DOCK_EN_1 (0x1 << 3) + +/* TDM2 Setting-2 (0x0120) */ +#define RT1011_TDM_I2S_DOCK_ADCDAT_LEN_2_MASK (0x7 << 13) +#define RT1011_TDM_I2S_DOCK_EN_2_MASK (0x1 << 3) +#define RT1011_TDM_I2S_DOCK_EN_2_SFT 3 +#define RT1011_TDM_I2S_DOCK_EN_2 (0x1 << 3) + +/* MIXER 1 (0x0300) */ +#define RT1011_MIXER_MUTE_MIX_I_MASK (0x1 << 15) +#define RT1011_MIXER_MUTE_MIX_I_SFT 15 +#define RT1011_MIXER_MUTE_MIX_I (0x1 << 15) +#define RT1011_MIXER_MUTE_SUM_I_MASK (0x1 << 14) +#define RT1011_MIXER_MUTE_SUM_I_SFT 14 +#define RT1011_MIXER_MUTE_SUM_I (0x1 << 14) +#define RT1011_MIXER_MUTE_MIX_V_MASK (0x1 << 7) +#define RT1011_MIXER_MUTE_MIX_V_SFT 7 +#define RT1011_MIXER_MUTE_MIX_V (0x1 << 7) +#define RT1011_MIXER_MUTE_SUM_V_MASK (0x1 << 6) +#define RT1011_MIXER_MUTE_SUM_V_SFT 6 +#define RT1011_MIXER_MUTE_SUM_V (0x1 << 6) + +/* Analog Temperature Sensor (0x0316) */ +#define RT1011_POW_TEMP_REG (0x1 << 2) +#define RT1011_POW_TEMP_REG_BIT 2 + +/* POWER-1 (0x0322) */ +#define RT1011_POW_LDO2 (0x1 << 15) +#define RT1011_POW_LDO2_BIT 15 +#define RT1011_POW_DAC (0x1 << 14) +#define RT1011_POW_DAC_BIT 14 +#define RT1011_POW_CLK12M (0x1 << 13) +#define RT1011_POW_CLK12M_BIT 13 +#define RT1011_POW_TEMP (0x1 << 12) +#define RT1011_POW_TEMP_BIT 12 +#define RT1011_POW_ISENSE_SPK (0x1 << 7) +#define RT1011_POW_ISENSE_SPK_BIT 7 +#define RT1011_POW_LPF_SPK (0x1 << 6) +#define RT1011_POW_LPF_SPK_BIT 6 +#define RT1011_POW_VSENSE_SPK (0x1 << 5) +#define RT1011_POW_VSENSE_SPK_BIT 5 +#define RT1011_POW_TWO_BATTERY_SPK (0x1 << 4) +#define RT1011_POW_TWO_BATTERY_SPK_BIT 4 + +/* POWER-2 (0x0324) */ +#define RT1011_PLLEN (0x1 << 2) +#define RT1011_PLLEN_BIT 2 +#define RT1011_POW_BG (0x1 << 1) +#define RT1011_POW_BG_BIT 1 +#define RT1011_POW_BG_MBIAS_LV (0x1 << 0) +#define RT1011_POW_BG_MBIAS_LV_BIT 0 + +/* POWER-3 (0x0326) */ +#define RT1011_POW_DET_SPKVDD (0x1 << 15) +#define RT1011_POW_DET_SPKVDD_BIT 15 +#define RT1011_POW_DET_VBAT (0x1 << 14) +#define RT1011_POW_DET_VBAT_BIT 14 +#define RT1011_POW_FC (0x1 << 13) +#define RT1011_POW_FC_BIT 13 +#define RT1011_POW_MBIAS_LV (0x1 << 12) +#define RT1011_POW_MBIAS_LV_BIT 12 +#define RT1011_POW_ADC_I (0x1 << 11) +#define RT1011_POW_ADC_I_BIT 11 +#define RT1011_POW_ADC_V (0x1 << 10) +#define RT1011_POW_ADC_V_BIT 10 +#define RT1011_POW_ADC_T (0x1 << 9) +#define RT1011_POW_ADC_T_BIT 9 +#define RT1011_POWD_ADC_T (0x1 << 8) +#define RT1011_POWD_ADC_T_BIT 8 +#define RT1011_POW_MIX_I (0x1 << 7) +#define RT1011_POW_MIX_I_BIT 7 +#define RT1011_POW_MIX_V (0x1 << 6) +#define RT1011_POW_MIX_V_BIT 6 +#define RT1011_POW_SUM_I (0x1 << 5) +#define RT1011_POW_SUM_I_BIT 5 +#define RT1011_POW_SUM_V (0x1 << 4) +#define RT1011_POW_SUM_V_BIT 4 +#define RT1011_POW_MIX_T (0x1 << 2) +#define RT1011_POW_MIX_T_BIT 2 +#define RT1011_BYPASS_MIX_T (0x1 << 1) +#define RT1011_BYPASS_MIX_T_BIT 1 +#define RT1011_POW_VREF_LV (0x1 << 0) +#define RT1011_POW_VREF_LV_BIT 0 + +/* POWER-4 (0x0328) */ +#define RT1011_POW_EN_SWR (0x1 << 12) +#define RT1011_POW_EN_SWR_BIT 12 +#define RT1011_POW_EN_PASS_BGOK_SWR (0x1 << 10) +#define RT1011_POW_EN_PASS_BGOK_SWR_BIT 10 +#define RT1011_POW_EN_PASS_VPOK_SWR (0x1 << 9) +#define RT1011_POW_EN_PASS_VPOK_SWR_BIT 9 + +/* POWER-9 (0x032d) */ +#define RT1011_POW_SDB_REG_MASK (0x1 << 9) +#define RT1011_POW_SDB_REG_BIT 9 +#define RT1011_POW_SDB_REG (0x1 << 9) +#define RT1011_POW_SEL_SDB_MODE_MASK (0x1 << 6) +#define RT1011_POW_SEL_SDB_MODE_BIT 6 +#define RT1011_POW_SEL_SDB_MODE (0x1 << 6) +#define RT1011_POW_MNL_SDB_MASK (0x1 << 5) +#define RT1011_POW_MNL_SDB_BIT 5 +#define RT1011_POW_MNL_SDB (0x1 << 5) + +/* SPK Protection-Temperature Protection (0x050c) */ +#define RT1011_STP_EN_MASK (0x1 << 15) +#define RT1011_STP_EN_BIT 15 +#define RT1011_STP_EN (0x1 << 15) +#define RT1011_STP_RS_CLB_EN_MASK (0x1 << 14) +#define RT1011_STP_RS_CLB_EN_BIT 14 +#define RT1011_STP_RS_CLB_EN (0x1 << 14) + +/* SPK Protection-Temperature Protection-4 (0x0510) */ +#define RT1011_STP_R0_SELECT_MASK (0x3 << 6) +#define RT1011_STP_R0_SELECT_EFUSE (0x0 << 6) +#define RT1011_STP_R0_SELECT_START_VAL (0x1 << 6) +#define RT1011_STP_R0_SELECT_REG (0x2 << 6) +#define RT1011_STP_R0_SELECT_FORCE_ZERO (0x3 << 6) + +/* SPK Protection-Temperature Protection-6 (0x0512) */ +#define RT1011_STP_R0_EN_MASK (0x1 << 7) +#define RT1011_STP_R0_EN_BIT 7 +#define RT1011_STP_R0_EN (0x1 << 7) +#define RT1011_STP_T0_EN_MASK (0x1 << 6) +#define RT1011_STP_T0_EN_BIT 6 +#define RT1011_STP_T0_EN (0x1 << 6) + +/* ClassD Internal Setting-1 (0x1300) */ +#define RT1011_DRIVER_READY_SPK (0x1 << 12) +#define RT1011_DRIVER_READY_SPK_BIT 12 +#define RT1011_RECV_MODE_SPK_MASK (0x1 << 5) +#define RT1011_SPK_MODE (0x0 << 5) +#define RT1011_RECV_MODE (0x1 << 5) +#define RT1011_RECV_MODE_SPK_BIT 5 + +/* ClassD Internal Setting-3 (0x1304) */ +#define RT1011_REG_GAIN_CLASSD_RI_SPK_MASK (0x7 << 12) +#define RT1011_REG_GAIN_CLASSD_RI_410K (0x0 << 12) +#define RT1011_REG_GAIN_CLASSD_RI_95K (0x1 << 12) +#define RT1011_REG_GAIN_CLASSD_RI_82P5K (0x2 << 12) +#define RT1011_REG_GAIN_CLASSD_RI_72P5K (0x3 << 12) +#define RT1011_REG_GAIN_CLASSD_RI_62P5K (0x4 << 12) + +/* ClassD Internal Setting-8 (0x130c) */ +#define RT1011_TM_PORPVDD_SPK (0x1 << 1) +#define RT1011_TM_PORPVDD_SPK_BIT 1 + +/* SPK Protection-Temperature Protection-SINE_GEN_REG-1 (0x1500) */ +#define RT1011_STP_SIN_GEN_EN_MASK (0x1 << 13) +#define RT1011_STP_SIN_GEN_EN (0x1 << 13) +#define RT1011_STP_SIN_GEN_EN_BIT 13 + + +/* System Clock Source */ +enum { + RT1011_FS_SYS_PRE_S_MCLK, + RT1011_FS_SYS_PRE_S_BCLK, + RT1011_FS_SYS_PRE_S_PLL1, + RT1011_FS_SYS_PRE_S_RCCLK, /* 12M Hz */ +}; + +/* PLL Source 1/2 */ +enum { + RT1011_PLL1_S_BCLK, + RT1011_PLL2_S_MCLK, + RT1011_PLL2_S_RCCLK, /* 12M Hz */ +}; + +enum { + RT1011_AIF1, + RT1011_AIFS +}; + +/* BiQual & DRC related settings */ +#define RT1011_BQ_DRC_NUM 128 +struct rt1011_bq_drc_params { + unsigned short val; + unsigned short reg; +#ifdef CONFIG_64BIT + unsigned int reserved; +#endif +}; +enum { + RT1011_ADVMODE_INITIAL_SET, + RT1011_ADVMODE_SEP_BQ_COEFF, + RT1011_ADVMODE_EQ_BQ_COEFF, + RT1011_ADVMODE_BQ_UI_COEFF, + RT1011_ADVMODE_SMARTBOOST_COEFF, + RT1011_ADVMODE_NUM, +}; + +struct rt1011_priv { + struct snd_soc_component *component; + struct regmap *regmap; + struct work_struct cali_work; + struct rt1011_bq_drc_params **bq_drc_params; + + int sysclk; + int sysclk_src; + int lrck; + int bclk; + int id; + + int pll_src; + int pll_in; + int pll_out; + + int bq_drc_set; + unsigned int r0_reg; + int recv_spk_mode; +}; + +#endif /* end of _RT1011_H_ */ From 190d9e0332ab43b28cbb1856fc73ed7fafbfad7c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 25 May 2019 20:32:04 +0800 Subject: [PATCH 144/626] ASoC: cx2072x: remove set but not used variable 'is_right_j ' Fixes gcc '-Wunused-but-set-variable' warning: sound/soc/codecs/cx2072x.c: In function cx2072x_config_i2spcm: sound/soc/codecs/cx2072x.c:679:6: warning: variable is_right_j set but not used [-Wunused-but-set-variable] It's never used and can be removed. Signed-off-by: YueHaibing Reviewed-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index 8b0830854bb3..f2cb35a50726 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -676,7 +676,6 @@ static int cx2072x_config_i2spcm(struct cx2072x_priv *cx2072x) unsigned int bclk_rate = 0; int is_i2s = 0; int has_one_bit_delay = 0; - int is_right_j = 0; int is_frame_inv = 0; int is_bclk_inv = 0; int pulse_len; @@ -740,7 +739,6 @@ static int cx2072x_config_i2spcm(struct cx2072x_priv *cx2072x) case SND_SOC_DAIFMT_RIGHT_J: is_i2s = 1; - is_right_j = 1; pulse_len = frame_len / 2; break; From 52194513ba1388443a067cee9606d6fe27e7650e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 29 May 2019 23:04:37 +0800 Subject: [PATCH 145/626] ASoC: mediatek: Make some symbols static Fix sparse warnings: sound/soc/mediatek/common/mtk-btcvsd.c:410:5: warning: symbol 'mtk_btcvsd_write_to_bt' was not declared. Should it be static? sound/soc/mediatek/common/mtk-btcvsd.c:698:9: warning: symbol 'mtk_btcvsd_snd_read' was not declared. Should it be static? sound/soc/mediatek/common/mtk-btcvsd.c:779:9: warning: symbol 'mtk_btcvsd_snd_write' was not declared. Should it be static? Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-btcvsd.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c index bd55c546e790..c7a81c4be068 100644 --- a/sound/soc/mediatek/common/mtk-btcvsd.c +++ b/sound/soc/mediatek/common/mtk-btcvsd.c @@ -407,11 +407,11 @@ static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt, return 0; } -int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt, - enum bt_sco_packet_len packet_type, - unsigned int packet_length, - unsigned int packet_num, - unsigned int blk_size) +static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt, + enum bt_sco_packet_len packet_type, + unsigned int packet_length, + unsigned int packet_num, + unsigned int blk_size) { unsigned int i; unsigned long flags; @@ -695,9 +695,9 @@ static int wait_for_bt_irq(struct mtk_btcvsd_snd *bt, return 0; } -ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt, - char __user *buf, - size_t count) +static ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt, + char __user *buf, + size_t count) { ssize_t read_size = 0, read_count = 0, cur_read_idx, cont; unsigned int cur_buf_ofs = 0; @@ -776,9 +776,9 @@ ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt, return read_count; } -ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt, - char __user *buf, - size_t count) +static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt, + char __user *buf, + size_t count) { int written_size = count, avail = 0, cur_write_idx, write_size, cont; unsigned int cur_buf_ofs = 0; From 9b8e8b893ff52264df2b54a6820ae3c4bb820624 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Jun 2019 14:12:49 +0300 Subject: [PATCH 146/626] ASoC: pcm3168a: Implement set_tdm_slot callback Initially we only going to care about the slot_width as for example DSP_A/B needs 32 bclk per slots and to be able to use TDM mode the codec (and CPU) needs to use DSP_A/B modes. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 60 ++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index e0d5839fe1a7..9eb24ca09793 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -56,6 +56,9 @@ struct pcm3168a_priv { unsigned long sysclk; unsigned int adc_fmt; unsigned int dac_fmt; + int tdm_slots; + u32 tdm_mask[2]; + int slot_width; }; static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" }; @@ -387,6 +390,41 @@ static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai, return pcm3168a_set_dai_fmt(dai, format, false); } +static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, + int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); + + if (tx_mask >= (1<= (1<dev, + "Bad tdm mask tx: 0x%08x rx: 0x%08x slots %d\n", + tx_mask, rx_mask, slots); + return -EINVAL; + } + + if (slot_width && + (slot_width != 16 && slot_width != 24 && slot_width != 32 )) { + dev_err(component->dev, "Unsupported slot_width %d\n", + slot_width); + return -EINVAL; + } + + pcm3168a->tdm_slots = slots; + pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; + pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; + + if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) { + dev_err(component->dev, "Not matching slot_width %d vs %d\n", + pcm3168a->slot_width, slot_width); + return -EINVAL; + } + + pcm3168a->slot_width = slot_width; + return 0; +} + static int pcm3168a_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -431,22 +469,26 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - min_frame_size = params_width(params) * 2; + if (pcm3168a->slot_width) + min_frame_size = pcm3168a->slot_width; + else + min_frame_size = params_width(params); + switch (min_frame_size) { - case 32: + case 16: if (master_mode || (fmt != PCM3168A_FMT_RIGHT_J)) { - dev_err(component->dev, "32-bit frames are supported only for slave mode using right justified\n"); + dev_err(component->dev, "16-bit slots are supported only for slave mode using right justified\n"); return -EINVAL; } fmt = PCM3168A_FMT_RIGHT_J_16; break; - case 48: + case 24: if (master_mode || (fmt & PCM3168A_FMT_DSP_MASK)) { - dev_err(component->dev, "48-bit frames not supported in master mode, or slave mode using DSP\n"); + dev_err(component->dev, "24-bit slots not supported in master mode, or slave mode using DSP\n"); return -EINVAL; } break; - case 64: + case 32: break; default: dev_err(component->dev, "unsupported frame size: %d\n", min_frame_size); @@ -554,14 +596,16 @@ static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { .set_fmt = pcm3168a_set_dai_fmt_dac, .set_sysclk = pcm3168a_set_dai_sysclk, .hw_params = pcm3168a_hw_params, - .digital_mute = pcm3168a_digital_mute + .digital_mute = pcm3168a_digital_mute, + .set_tdm_slot = pcm3168a_set_tdm_slot, }; static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = { .startup = pcm3168a_startup, .set_fmt = pcm3168a_set_dai_fmt_adc, .set_sysclk = pcm3168a_set_dai_sysclk, - .hw_params = pcm3168a_hw_params + .hw_params = pcm3168a_hw_params, + .set_tdm_slot = pcm3168a_set_tdm_slot, }; static struct snd_soc_dai_driver pcm3168a_dais[] = { From 619c15f7fac98fbeaae02d76a5529f5026a2b6d7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 5 Jun 2019 12:08:01 +0200 Subject: [PATCH 147/626] ASoC: sun4i-i2s: Change SR and WSS computation The current computation for the SR (sample resolution) and the WSS (word slot size) register parameters is based on a switch returning the matching parameters for a given params width. Later SoCs (A83t, H3, A64) changed that calculation, which was loosely the same with an offset. Therefore, an offset was added to adjust those parameters. However, the calculation is a bit less trivial than initially thought. Indeed, while we assumed that SR and WSS were always the same, on older SoCs, SR will max at 24 (since those SoCs do not support 32 bits formats), but the word size can be 32. Newer SoCs can also support a much larger range (8 bits to 32 bits, by increments of 4) of size than the older SoCs could. Finally, the A64 and A83t were never adjusted to have that offset in the first place, and were therefore broken from that point of view. In order to fix all those issues, let's introduce two functions, get_wss and get_sr, with their respective implementations for all the SoCs supported so far. Fixes: 21faaea1343f ("ASoC: sun4i-i2s: Add support for A83T") Fixes: 66ecce332538 ("ASoC: sun4i-i2s: Add compatibility with A64 codec I2S") Signed-off-by: Maxime Ripard Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 73 ++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index d5ec1a20499d..03696f880080 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -118,6 +118,8 @@ #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 +struct sun4i_i2s; + /** * struct sun4i_i2s_quirks - Differences between SoC variants. * @@ -131,7 +133,6 @@ * @sun4i_i2s_regmap: regmap config to use. * @mclk_offset: Value by which mclkdiv needs to be adjusted. * @bclk_offset: Value by which bclkdiv needs to be adjusted. - * @fmt_offset: Value by which wss and sr needs to be adjusted. * @field_clkdiv_mclk_en: regmap field to enable mclk output. * @field_fmt_wss: regmap field to set word select size. * @field_fmt_sr: regmap field to set sample resolution. @@ -154,7 +155,6 @@ struct sun4i_i2s_quirks { const struct regmap_config *sun4i_i2s_regmap; unsigned int mclk_offset; unsigned int bclk_offset; - unsigned int fmt_offset; /* Register fields for i2s */ struct reg_field field_clkdiv_mclk_en; @@ -167,6 +167,9 @@ struct sun4i_i2s_quirks { struct reg_field field_rxchanmap; struct reg_field field_txchansel; struct reg_field field_rxchansel; + + s8 (*get_sr)(const struct sun4i_i2s *, int); + s8 (*get_wss)(const struct sun4i_i2s *, int); }; struct sun4i_i2s { @@ -349,6 +352,39 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, return 0; } +static s8 sun4i_i2s_get_sr(const struct sun4i_i2s *i2s, int width) +{ + if (width < 16 || width > 24) + return -EINVAL; + + if (width % 4) + return -EINVAL; + + return (width - 16) / 4; +} + +static s8 sun4i_i2s_get_wss(const struct sun4i_i2s *i2s, int width) +{ + if (width < 16 || width > 32) + return -EINVAL; + + if (width % 4) + return -EINVAL; + + return (width - 16) / 4; +} + +static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width) +{ + if (width % 4) + return -EINVAL; + + if (width < 8 || width > 32) + return -EINVAL; + + return (width - 8) / 4 + 1; +} + static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -400,22 +436,16 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, } i2s->playback_dma_data.addr_width = width; - switch (params_width(params)) { - case 16: - sr = 0; - wss = 0; - break; - - default: - dev_err(dai->dev, "Unsupported sample width: %d\n", - params_width(params)); + sr = i2s->variant->get_sr(i2s, params_width(params)); + if (sr < 0) return -EINVAL; - } - regmap_field_write(i2s->field_fmt_wss, - wss + i2s->variant->fmt_offset); - regmap_field_write(i2s->field_fmt_sr, - sr + i2s->variant->fmt_offset); + wss = i2s->variant->get_wss(i2s, params_width(params)); + if (wss < 0) + return -EINVAL; + + regmap_field_write(i2s->field_fmt_wss, wss); + regmap_field_write(i2s->field_fmt_sr, sr); return sun4i_i2s_set_clk_rate(dai, params_rate(params), params_width(params)); @@ -891,6 +921,8 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun4i_i2s_get_sr, + .get_wss = sun4i_i2s_get_wss, }; static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { @@ -908,6 +940,8 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun4i_i2s_get_sr, + .get_wss = sun4i_i2s_get_wss, }; static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { @@ -925,6 +959,8 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { @@ -933,7 +969,6 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, .mclk_offset = 1, .bclk_offset = 2, - .fmt_offset = 3, .has_fmt_set_lrck_period = true, .has_chcfg = true, .has_chsel_tx_chen = true, @@ -948,6 +983,8 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { @@ -965,6 +1002,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static int sun4i_i2s_init_regmap_fields(struct device *dev, From 3bb936f5b92a0a6b6f4d16d834243e2f62521349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Wed, 5 Jun 2019 15:45:53 +0200 Subject: [PATCH 148/626] ASoC: core: Tell codec that jack is being removed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When component is being removed we should disable jack, otherwise some codecs will try to trigger interrupt using freed structures. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7abb017a83f3..ace5fb01d9a0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -951,6 +951,7 @@ _err_defer: static void soc_cleanup_component(struct snd_soc_component *component) { + snd_soc_component_set_jack(component, NULL, NULL); list_del(&component->card_list); snd_soc_dapm_free(snd_soc_component_get_dapm(component)); soc_cleanup_component_debugfs(component); From 83a6edbb8fe928e801b9b6cab13e81109b185918 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 5 Jun 2019 22:12:27 -0700 Subject: [PATCH 149/626] ASoC: rt1011: Mark format integer literals as unsigned Clang warns: sound/soc/codecs/rt1011.c:1291:12: warning: integer literal is too large to be represented in type 'long', interpreting as 'unsigned long' per C89; this literal will have type 'long long' in C99 onwards [-Wc99-compat] format = 2147483648; /* 2^24 * 128 */ ^ sound/soc/codecs/rt1011.c:2123:13: warning: integer literal is too large to be represented in type 'long', interpreting as 'unsigned long' per C89; this literal will have type 'long long' in C99 onwards [-Wc99-compat] format = 2147483648; /* 2^24 * 128 */ ^ 2 warnings generated. Mark the integer literals as unsigned explicitly so that if the kernel does ever bump the C standard it uses, the behavior is consitent. Fixes: d6e65bb7ff0d ("ASoC: rt1011: Add RT1011 amplifier driver") Link: https://github.com/ClangBuiltLinux/linux/issues/506 Signed-off-by: Nathan Chancellor Reviewed-by: Nick Desaulniers Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 349d6db7ecd4..3a0ae80c5ee0 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1288,7 +1288,7 @@ static int rt1011_r0_load_mode_put(struct snd_kcontrol *kcontrol, if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { rt1011->r0_reg = ucontrol->value.integer.value[0]; - format = 2147483648; /* 2^24 * 128 */ + format = 2147483648U; /* 2^24 * 128 */ r0_integer = format / rt1011->r0_reg / 128; r0_factor = ((format / rt1011->r0_reg * 100) / 128) - (r0_integer * 100); @@ -2120,7 +2120,7 @@ static int rt1011_calibrate(struct rt1011_priv *rt1011, unsigned char cali_flag) dev_err(dev, "Calibrate R0 Failure\n"); ret = -EAGAIN; } else { - format = 2147483648; /* 2^24 * 128 */ + format = 2147483648U; /* 2^24 * 128 */ r0_integer = format / r0[0] / 128; r0_factor = ((format / r0[0] * 100) / 128) - (r0_integer * 100); From 64429a8711e121e5d5d93d970c5ed3492332dd18 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Thu, 6 Jun 2019 14:22:32 +0800 Subject: [PATCH 150/626] ASoC: rt1011: fix warning reported by kbuild test robot and minor issue This patch fixes following issues: - warning: this decimal constant is unsigned only in ISO C90 - sparse: incorrect type in assignment - check if value.integer.value is zero for "R0 Load Mode" control Signed-off-by: Shuming Fan Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 3a0ae80c5ee0..5605b660f4bf 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1145,8 +1145,8 @@ static int rt1011_bq_drc_coeff_get(struct snd_kcontrol *kcontrol, bq_drc_info = rt1011->bq_drc_params[mode_idx]; for (i = 0; i < RT1011_BQ_DRC_NUM; i++) { - params[i].reg = cpu_to_le16(bq_drc_info[i].reg); - params[i].val = cpu_to_le16(bq_drc_info[i].val); + params[i].reg = bq_drc_info[i].reg; + params[i].val = bq_drc_info[i].val; } return 0; @@ -1187,8 +1187,8 @@ static int rt1011_bq_drc_coeff_put(struct snd_kcontrol *kcontrol, pr_info("%s, id.name=%s, mode_idx=%d\n", __func__, ucontrol->id.name, mode_idx); for (i = 0; i < RT1011_BQ_DRC_NUM; i++) { - bq_drc_info[i].reg = le16_to_cpu(params[i].reg); - bq_drc_info[i].val = le16_to_cpu(params[i].val); + bq_drc_info[i].reg = params[i].reg; + bq_drc_info[i].val = params[i].val; } for (i = 0; i < RT1011_BQ_DRC_NUM; i++) { @@ -1284,6 +1284,9 @@ static int rt1011_r0_load_mode_put(struct snd_kcontrol *kcontrol, if (!component->card->instantiated) return 0; + if (ucontrol->value.integer.value[0] == 0) + return -EINVAL; + dev = regmap_get_device(rt1011->regmap); if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { rt1011->r0_reg = ucontrol->value.integer.value[0]; From 08a5841e3a109f9ea7bfa9c64109aefa95a318c7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:07:22 +0900 Subject: [PATCH 151/626] ASoC: soc-core: use snd_soc_dai_link_component for CPU current ALSA SoC is starting to support modern style dai_linke (= struct snd_soc_dai_link_component) which is mainly used for multipul DAI/component connection. Now Codec has full multi-codec support, Platform is using modern style but still for single Platform. Only CPU is not yet supporting modern style yet. If we could support it for CPU, we can switch to modern style dai_link on all CPU/Codec/Platform, and remove legacy style from ALSA SoC. Multi-CPU will be supported in the future. This patch is initial support for modern style for CPU Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 4 +++ sound/soc/soc-core.c | 83 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index f20785aa7b4a..ae7ca828e167 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -927,6 +927,9 @@ struct snd_soc_dai_link { */ const char *cpu_dai_name; + struct snd_soc_dai_link_component *cpus; + unsigned int num_cpus; + /* * codec_name * codec_of_node @@ -1035,6 +1038,7 @@ struct snd_soc_dai_link { * drivers should not modify this value. */ unsigned int legacy_platform:1; + unsigned int legacy_cpu:1; struct list_head list; /* DAI link list of the soc card */ struct snd_soc_dobj dobj; /* For topology */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ace5fb01d9a0..f86ee4f48f06 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -887,7 +887,6 @@ static int soc_bind_dai_link(struct snd_soc_card *card, { struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai_link_component *codecs; - struct snd_soc_dai_link_component cpu_dai_component; struct snd_soc_component *component; int i; @@ -906,13 +905,11 @@ static int soc_bind_dai_link(struct snd_soc_card *card, if (!rtd) return -ENOMEM; - cpu_dai_component.name = dai_link->cpu_name; - cpu_dai_component.of_node = dai_link->cpu_of_node; - cpu_dai_component.dai_name = dai_link->cpu_dai_name; - rtd->cpu_dai = snd_soc_find_dai(&cpu_dai_component); + /* FIXME: we need multi CPU support in the future */ + rtd->cpu_dai = snd_soc_find_dai(dai_link->cpus); if (!rtd->cpu_dai) { dev_info(card->dev, "ASoC: CPU DAI %s not registered\n", - dai_link->cpu_dai_name); + dai_link->cpus->dai_name); goto _err_defer; } snd_soc_rtdcom_add(rtd, rtd->cpu_dai->component); @@ -1049,6 +1046,46 @@ static void soc_remove_dai_links(struct snd_soc_card *card) } } +static int snd_soc_init_cpu(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link) +{ + struct snd_soc_dai_link_component *cpu = dai_link->cpus; + + /* + * REMOVE ME + * + * This is glue code for Legacy vs Modern dai_link. + * This function will be removed if all derivers are switched to + * modern style dai_link. + * Driver shouldn't use both legacy and modern style in the same time. + * see + * soc.h :: struct snd_soc_dai_link + */ + /* convert Legacy platform link */ + if (!cpu) { + cpu = devm_kzalloc(card->dev, + sizeof(struct snd_soc_dai_link_component), + GFP_KERNEL); + if (!cpu) + return -ENOMEM; + + dai_link->cpus = cpu; + dai_link->num_cpus = 1; + dai_link->legacy_cpu = 1; + + cpu->name = dai_link->cpu_name; + cpu->of_node = dai_link->cpu_of_node; + cpu->dai_name = dai_link->cpu_dai_name; + } + + if (!dai_link->cpus) { + dev_err(card->dev, "ASoC: DAI link has no CPUs\n"); + return -EINVAL; + } + + return 0; +} + static int snd_soc_init_platform(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { @@ -1088,7 +1125,7 @@ static int snd_soc_init_platform(struct snd_soc_card *card, return 0; } -static void soc_cleanup_platform(struct snd_soc_card *card) +static void soc_cleanup_legacy(struct snd_soc_card *card) { struct snd_soc_dai_link *link; int i; @@ -1103,6 +1140,10 @@ static void soc_cleanup_platform(struct snd_soc_card *card) link->legacy_platform = 0; link->platforms = NULL; } + if (link->legacy_cpu) { + link->legacy_cpu = 0; + link->cpus = NULL; + } } } @@ -1150,6 +1191,12 @@ static int soc_init_dai_link(struct snd_soc_card *card, int i, ret; struct snd_soc_dai_link_component *codec; + ret = snd_soc_init_cpu(card, link); + if (ret) { + dev_err(card->dev, "ASoC: failed to init cpu\n"); + return ret; + } + ret = snd_soc_init_platform(card, link); if (ret) { dev_err(card->dev, "ASoC: failed to init multiplatform\n"); @@ -1208,12 +1255,20 @@ static int soc_init_dai_link(struct snd_soc_card *card, !soc_find_component(link->platforms->of_node, link->platforms->name)) return -EPROBE_DEFER; + /* FIXME */ + if (link->num_cpus > 1) { + dev_err(card->dev, + "ASoC: multi cpu is not yet supported %s\n", + link->name); + return -EINVAL; + } + /* * CPU device may be specified by either name or OF node, but * can be left unspecified, and will be matched based on DAI * name alone.. */ - if (link->cpu_name && link->cpu_of_node) { + if (link->cpus->name && link->cpus->of_node) { dev_err(card->dev, "ASoC: Neither/both cpu name/of_node are set for %s\n", link->name); @@ -1224,16 +1279,16 @@ static int soc_init_dai_link(struct snd_soc_card *card, * Defer card registartion if cpu dai component is not added to * component list. */ - if ((link->cpu_of_node || link->cpu_name) && - !soc_find_component(link->cpu_of_node, link->cpu_name)) + if ((link->cpus->of_node || link->cpus->name) && + !soc_find_component(link->cpus->of_node, link->cpus->name)) return -EPROBE_DEFER; /* * At least one of CPU DAI name or CPU device name/node must be * specified */ - if (!link->cpu_dai_name && - !(link->cpu_name || link->cpu_of_node)) { + if (!link->cpus->dai_name && + !(link->cpus->name || link->cpus->of_node)) { dev_err(card->dev, "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", link->name); @@ -2049,7 +2104,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) /* remove and free each DAI */ soc_remove_dai_links(card); soc_remove_pcm_runtimes(card); - soc_cleanup_platform(card); + soc_cleanup_legacy(card); /* remove auxiliary devices */ soc_remove_aux_devices(card); @@ -2806,7 +2861,7 @@ int snd_soc_register_card(struct snd_soc_card *card) ret = soc_init_dai_link(card, link); if (ret) { - soc_cleanup_platform(card); + soc_cleanup_legacy(card); dev_err(card->dev, "ASoC: failed to init link %s\n", link->name); mutex_unlock(&client_mutex); From f107294c6422e772773b53dbf802186175b6289e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:07:35 +0900 Subject: [PATCH 152/626] ASoC: simple-card: support snd_soc_dai_link_component style for cpu ASoC supports modern style dai_link (= snd_soc_dai_link_component) for CPU. legacy style dai_link (= cpu_dai_name, cpu_name, cpu_of_node) are no longer needed. This patch switches to modern style. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 20 +++++--------- sound/soc/generic/audio-graph-card.c | 30 ++++++--------------- sound/soc/generic/simple-card-utils.c | 21 +++++---------- sound/soc/generic/simple-card.c | 39 ++++++++++----------------- 4 files changed, 34 insertions(+), 76 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 3429888347e7..954563ee2277 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -42,6 +42,7 @@ struct asoc_simple_priv { struct simple_dai_props { struct asoc_simple_dai *cpu_dai; struct asoc_simple_dai *codec_dai; + struct snd_soc_dai_link_component cpus; /* single cpu */ struct snd_soc_dai_link_component codecs; /* single codec */ struct snd_soc_dai_link_component platforms; struct asoc_simple_data adata; @@ -80,16 +81,12 @@ int asoc_simple_parse_card_name(struct snd_soc_card *card, char *prefix); #define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \ - asoc_simple_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai, \ - dai_link->cpu_dai_name, NULL) + asoc_simple_parse_clk(dev, node, simple_dai, dai_link->cpus) #define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \ - asoc_simple_parse_clk(dev, node, dai_link->codec_of_node, simple_dai,\ - dai_link->codec_dai_name, dai_link->codecs) + asoc_simple_parse_clk(dev, node, simple_dai, dai_link->codecs) int asoc_simple_parse_clk(struct device *dev, struct device_node *node, - struct device_node *dai_of_node, struct asoc_simple_dai *simple_dai, - const char *dai_name, struct snd_soc_dai_link_component *dlc); int asoc_simple_startup(struct snd_pcm_substream *substream); void asoc_simple_shutdown(struct snd_pcm_substream *substream); @@ -100,16 +97,11 @@ int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); #define asoc_simple_parse_cpu(node, dai_link, is_single_link) \ - asoc_simple_parse_dai(node, NULL, \ - &dai_link->cpu_of_node, \ - &dai_link->cpu_dai_name, is_single_link) + asoc_simple_parse_dai(node, dai_link->cpus, is_single_link) #define asoc_simple_parse_codec(node, dai_link) \ - asoc_simple_parse_dai(node, dai_link->codecs, \ - &dai_link->codec_of_node, \ - &dai_link->codec_dai_name, NULL) + asoc_simple_parse_dai(node, dai_link->codecs, NULL) #define asoc_simple_parse_platform(node, dai_link) \ - asoc_simple_parse_dai(node, dai_link->platforms, \ - &dai_link->platform_of_node, NULL, NULL) + asoc_simple_parse_dai(node, dai_link->platforms, NULL) #define asoc_simple_parse_tdm(np, dai) \ snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \ diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index ec7e673ba475..e438011f5e45 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -111,29 +111,14 @@ static int graph_get_dai_id(struct device_node *ep) static int asoc_simple_parse_dai(struct device_node *ep, struct snd_soc_dai_link_component *dlc, - struct device_node **dai_of_node, - const char **dai_name, int *is_single_link) { struct device_node *node; struct of_phandle_args args; int ret; - /* - * Use snd_soc_dai_link_component instead of legacy style. - * It is only for codec, but cpu will be supported in the future. - * see - * soc-core.c :: snd_soc_init_multicodec() - */ - if (dlc) { - dai_name = &dlc->dai_name; - dai_of_node = &dlc->of_node; - } - if (!ep) return 0; - if (!dai_name) - return 0; node = of_graph_get_port_parent(ep); @@ -142,11 +127,11 @@ static int asoc_simple_parse_dai(struct device_node *ep, args.args[0] = graph_get_dai_id(ep); args.args_count = (of_graph_get_endpoint_count(node) > 1); - ret = snd_soc_get_dai_name(&args, dai_name); + ret = snd_soc_get_dai_name(&args, &dlc->dai_name); if (ret < 0) return ret; - *dai_of_node = node; + dlc->of_node = node; if (is_single_link) *is_single_link = of_graph_get_endpoint_count(node) == 1; @@ -207,6 +192,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *ports; struct device_node *node; struct asoc_simple_dai *dai; + struct snd_soc_dai_link_component *cpus = dai_link->cpus; struct snd_soc_dai_link_component *codecs = dai_link->codecs; int ret; @@ -251,7 +237,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = asoc_simple_set_dailink_name(dev, dai_link, "fe.%s", - dai_link->cpu_dai_name); + cpus->dai_name); if (ret < 0) return ret; @@ -261,9 +247,9 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct snd_soc_codec_conf *cconf; /* 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"; + cpus->of_node = NULL; + cpus->dai_name = "snd-soc-dummy-dai"; + cpus->name = "snd-soc-dummy"; /* BE settings */ dai_link->no_pcm = 1; @@ -383,7 +369,7 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, ret = asoc_simple_set_dailink_name(dev, dai_link, "%s-%s", - dai_link->cpu_dai_name, + dai_link->cpus->dai_name, dai_link->codecs->dai_name); if (ret < 0) return ret; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index f4c6375d11c7..ac8678fe55ff 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -159,23 +159,12 @@ static void asoc_simple_clk_disable(struct asoc_simple_dai *dai) int asoc_simple_parse_clk(struct device *dev, struct device_node *node, - struct device_node *dai_of_node, struct asoc_simple_dai *simple_dai, - const char *dai_name, struct snd_soc_dai_link_component *dlc) { struct clk *clk; u32 val; - /* - * Use snd_soc_dai_link_component instead of legacy style. - * It is only for codec, but cpu will be supported in the future. - * see - * soc-core.c :: snd_soc_init_multicodec() - */ - if (dlc) - dai_of_node = dlc->of_node; - /* * Parse dai->sysclk come from "clocks = <&xxx>" * (if system has common clock) @@ -190,7 +179,7 @@ int asoc_simple_parse_clk(struct device *dev, } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { simple_dai->sysclk = val; } else { - clk = devm_get_clk_from_child(dev, dai_of_node, NULL); + clk = devm_get_clk_from_child(dev, dlc->of_node, NULL); if (!IS_ERR(clk)) simple_dai->sysclk = clk_get_rate(clk); } @@ -359,7 +348,7 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link) { /* Assumes platform == cpu */ if (!dai_link->platforms->of_node) - dai_link->platforms->of_node = dai_link->cpu_of_node; + dai_link->platforms->of_node = dai_link->cpus->of_node; } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); @@ -376,7 +365,7 @@ void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link, * fmt_multiple_name() */ if (is_single_links) - dai_link->cpu_dai_name = NULL; + dai_link->cpus->dai_name = NULL; } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_cpu); @@ -386,7 +375,7 @@ int asoc_simple_clean_reference(struct snd_soc_card *card) int i; for_each_card_prelinks(card, i, dai_link) { - of_node_put(dai_link->cpu_of_node); + of_node_put(dai_link->cpus->of_node); of_node_put(dai_link->codecs->of_node); } return 0; @@ -576,6 +565,8 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, * simple-card-utils.c :: asoc_simple_canonicalize_platform() */ for (i = 0; i < li->link; i++) { + dai_link[i].cpus = &dai_props[i].cpus; + dai_link[i].num_cpus = 1; dai_link[i].codecs = &dai_props[i].codecs; dai_link[i].num_codecs = 1; dai_link[i].platforms = &dai_props[i].platforms; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index d16e894fce2b..e5cde0d5e63c 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -30,8 +30,6 @@ static const struct snd_soc_ops simple_ops = { static int asoc_simple_parse_dai(struct device_node *node, struct snd_soc_dai_link_component *dlc, - struct device_node **dai_of_node, - const char **dai_name, int *is_single_link) { struct of_phandle_args args; @@ -40,17 +38,6 @@ static int asoc_simple_parse_dai(struct device_node *node, if (!node) return 0; - /* - * Use snd_soc_dai_link_component instead of legacy style. - * It is only for codec, but cpu will be supported in the future. - * see - * soc-core.c :: snd_soc_init_multicodec() - */ - if (dlc) { - dai_name = &dlc->dai_name; - dai_of_node = &dlc->of_node; - } - /* * Get node via "sound-dai = <&phandle port>" * it will be used as xxx_of_node on soc_bind_dai_link() @@ -60,13 +47,11 @@ static int asoc_simple_parse_dai(struct device_node *node, return ret; /* Get dai->name */ - if (dai_name) { - ret = snd_soc_of_get_dai_name(node, dai_name); - if (ret < 0) - return ret; - } + ret = snd_soc_of_get_dai_name(node, &dlc->dai_name); + if (ret < 0) + return ret; - *dai_of_node = args.np; + dlc->of_node = args.np; if (is_single_link) *is_single_link = !args.args_count; @@ -119,6 +104,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct asoc_simple_dai *dai; + struct snd_soc_dai_link_component *cpus = dai_link->cpus; struct snd_soc_dai_link_component *codecs = dai_link->codecs; struct device_node *top = dev->of_node; struct device_node *node = of_get_parent(np); @@ -169,7 +155,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = asoc_simple_set_dailink_name(dev, dai_link, "fe.%s", - dai_link->cpu_dai_name); + cpus->dai_name); if (ret < 0) return ret; @@ -178,9 +164,9 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct snd_soc_codec_conf *cconf; /* 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"; + cpus->of_node = NULL; + cpus->dai_name = "snd-soc-dummy-dai"; + cpus->name = "snd-soc-dummy"; /* BE settings */ dai_link->no_pcm = 1; @@ -320,7 +306,7 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, ret = asoc_simple_set_dailink_name(dev, dai_link, "%s-%s", - dai_link->cpu_dai_name, + dai_link->cpus->dai_name, dai_link->codecs->dai_name); if (ret < 0) goto dai_link_of_err; @@ -646,6 +632,7 @@ static int asoc_simple_probe(struct platform_device *pdev) } else { struct asoc_simple_card_info *cinfo; + struct snd_soc_dai_link_component *cpus; struct snd_soc_dai_link_component *codecs; struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dai_link = priv->dai_link; @@ -671,6 +658,9 @@ static int asoc_simple_probe(struct platform_device *pdev) dai_props->cpu_dai = &priv->dais[dai_idx++]; dai_props->codec_dai = &priv->dais[dai_idx++]; + cpus = dai_link->cpus; + cpus->dai_name = cinfo->cpu_dai.name; + codecs = dai_link->codecs; codecs->name = cinfo->codec; codecs->dai_name = cinfo->codec_dai.name; @@ -681,7 +671,6 @@ static int asoc_simple_probe(struct platform_device *pdev) card->name = (cinfo->card) ? cinfo->card : cinfo->name; dai_link->name = cinfo->name; dai_link->stream_name = cinfo->name; - dai_link->cpu_dai_name = cinfo->cpu_dai.name; dai_link->dai_fmt = cinfo->daifmt; dai_link->init = asoc_simple_dai_init; memcpy(dai_props->cpu_dai, &cinfo->cpu_dai, From 587c984427bf7d031a2a4b693dfb24a51cd660b2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:07:42 +0900 Subject: [PATCH 153/626] ASoC: soc.h: add sound dai_link connection macro Modern style dai_link requests CPU/Codec/Platform component pointer array and its size, but it will be very verbose code. To avoid such scene, this patch adds dai_link connection macro. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 88 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/soc-core.c | 7 ++++ 2 files changed, 95 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index ae7ca828e167..0fa79b8330d7 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1048,6 +1048,94 @@ struct snd_soc_dai_link { ((i) < link->num_codecs) && ((codec) = &link->codecs[i]); \ (i)++) +/* + * Sample 1 : Single CPU/Codec/Platform + * + * SND_SOC_DAILINK_DEFS(test, + * DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai")), + * DAILINK_COMP_ARRAY(COMP_CODEC("codec", "codec_dai")), + * DAILINK_COMP_ARRAY(COMP_PLATFORM("platform"))); + * + * struct snd_soc_dai_link link = { + * ... + * SND_SOC_DAILINK_REG(test), + * }; + * + * Sample 2 : Multi CPU/Codec, no Platform + * + * SND_SOC_DAILINK_DEFS(test, + * DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai1"), + * COMP_CPU("cpu_dai2")), + * DAILINK_COMP_ARRAY(COMP_CODEC("codec1", "codec_dai1"), + * COMP_CODEC("codec2", "codec_dai2"))); + * + * struct snd_soc_dai_link link = { + * ... + * SND_SOC_DAILINK_REG(test), + * }; + * + * Sample 3 : Define each CPU/Codec/Platform manually + * + * SND_SOC_DAILINK_DEF(test_cpu, + * DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai1"), + * COMP_CPU("cpu_dai2"))); + * SND_SOC_DAILINK_DEF(test_codec, + * DAILINK_COMP_ARRAY(COMP_CODEC("codec1", "codec_dai1"), + * COMP_CODEC("codec2", "codec_dai2"))); + * SND_SOC_DAILINK_DEF(test_platform, + * DAILINK_COMP_ARRAY(COMP_PLATFORM("platform"))); + * + * struct snd_soc_dai_link link = { + * ... + * SND_SOC_DAILINK_REG(test_cpu, + * test_codec, + * test_platform), + * }; + * + * Sample 4 : Sample3 without platform + * + * struct snd_soc_dai_link link = { + * ... + * SND_SOC_DAILINK_REG(test_cpu, + * test_codec); + * }; + */ + +#define SND_SOC_DAILINK_REG1(name) SND_SOC_DAILINK_REG3(name##_cpus, name##_codecs, name##_platforms) +#define SND_SOC_DAILINK_REG2(cpu, codec) SND_SOC_DAILINK_REG3(cpu, codec, null_dailink_component) +#define SND_SOC_DAILINK_REG3(cpu, codec, platform) \ + .cpus = cpu, \ + .num_cpus = ARRAY_SIZE(cpu), \ + .codecs = codec, \ + .num_codecs = ARRAY_SIZE(codec), \ + .platforms = platform, \ + .num_platforms = ARRAY_SIZE(platform) + +#define SND_SOC_DAILINK_REGx(_1, _2, _3, func, ...) func +#define SND_SOC_DAILINK_REG(...) \ + SND_SOC_DAILINK_REGx(__VA_ARGS__, \ + SND_SOC_DAILINK_REG3, \ + SND_SOC_DAILINK_REG2, \ + SND_SOC_DAILINK_REG1)(__VA_ARGS__) + +#define SND_SOC_DAILINK_DEF(name, def...) \ + static struct snd_soc_dai_link_component name[] = { def } + +#define SND_SOC_DAILINK_DEFS(name, cpu, codec, platform...) \ + SND_SOC_DAILINK_DEF(name##_cpus, cpu); \ + SND_SOC_DAILINK_DEF(name##_codecs, codec); \ + SND_SOC_DAILINK_DEF(name##_platforms, platform) + +#define DAILINK_COMP_ARRAY(param...) param +#define COMP_EMPTY() { } +#define COMP_CPU(_dai) { .dai_name = _dai, } +#define COMP_CODEC(_name, _dai) { .name = _name, .dai_name = _dai, } +#define COMP_PLATFORM(_name) { .name = _name } +#define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", } + +extern struct snd_soc_dai_link_component null_dailink_component[0]; + + struct snd_soc_codec_conf { /* * specify device either by device name, or by diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f86ee4f48f06..9bd6b08d79b5 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -57,6 +57,13 @@ static LIST_HEAD(unbind_card_list); #define for_each_component(component) \ list_for_each_entry(component, &component_list, list) +/* + * This is used if driver don't need to have CPU/Codec/Platform + * dai_link. see soc.h + */ +struct snd_soc_dai_link_component null_dailink_component[0]; +EXPORT_SYMBOL_GPL(null_dailink_component); + /* * This is a timeout to do a DAPM powerdown after a stream is closed(). * It can be used to eliminate pops between different playback streams, e.g. From 9ded5f71114bcf935051db12f0ad1abe4ef497b1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:07:49 +0900 Subject: [PATCH 154/626] ASoC: mediatek: mt6797-mt6351: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/mediatek/mt6797/mt6797-mt6351.c | 115 ++++++++++++++-------- 1 file changed, 76 insertions(+), 39 deletions(-) diff --git a/sound/soc/mediatek/mt6797/mt6797-mt6351.c b/sound/soc/mediatek/mt6797/mt6797-mt6351.c index cc41eb531653..496f32bcfb5e 100644 --- a/sound/soc/mediatek/mt6797/mt6797-mt6351.c +++ b/sound/soc/mediatek/mt6797/mt6797-mt6351.c @@ -10,140 +10,177 @@ #include "mt6797-afe-common.h" +SND_SOC_DAILINK_DEFS(playback_1, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback_2, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback_3, + DAILINK_COMP_ARRAY(COMP_CPU("DL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture_1, + DAILINK_COMP_ARRAY(COMP_CPU("UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture_2, + DAILINK_COMP_ARRAY(COMP_CPU("UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture_3, + DAILINK_COMP_ARRAY(COMP_CPU("UL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture_mono_1, + DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hostless_lpbk, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hostless_speech, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless Speech DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(primary_codec, + DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "mt6351-snd-codec-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(pcm1, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(pcm2, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = { /* FE */ { .name = "Playback_1", .stream_name = "Playback_1", - .cpu_dai_name = "DL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback_1), }, { .name = "Playback_2", .stream_name = "Playback_2", - .cpu_dai_name = "DL2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback_2), }, { .name = "Playback_3", .stream_name = "Playback_3", - .cpu_dai_name = "DL3", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback_3), }, { .name = "Capture_1", .stream_name = "Capture_1", - .cpu_dai_name = "UL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture_1), }, { .name = "Capture_2", .stream_name = "Capture_2", - .cpu_dai_name = "UL2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture_2), }, { .name = "Capture_3", .stream_name = "Capture_3", - .cpu_dai_name = "UL3", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture_3), }, { .name = "Capture_Mono_1", .stream_name = "Capture_Mono_1", - .cpu_dai_name = "UL_MONO_1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture_mono_1), }, { .name = "Hostless_LPBK", .stream_name = "Hostless_LPBK", - .cpu_dai_name = "Hostless LPBK DAI", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_lpbk), }, { .name = "Hostless_Speech", .stream_name = "Hostless_Speech", - .cpu_dai_name = "Hostless Speech DAI", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_speech), }, /* BE */ { .name = "Primary Codec", - .cpu_dai_name = "ADDA", - .codec_dai_name = "mt6351-snd-codec-aif1", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(primary_codec), }, { .name = "PCM 1", - .cpu_dai_name = "PCM 1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm1), }, { .name = "PCM 2", - .cpu_dai_name = "PCM 2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm2), }, }; @@ -170,9 +207,9 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) return -EINVAL; } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } codec_node = of_parse_phandle(pdev->dev.of_node, @@ -183,9 +220,9 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) return -EINVAL; } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->codec_name) + if (dai_link->codecs->name) continue; - dai_link->codec_of_node = codec_node; + dai_link->codecs->of_node = codec_node; } ret = devm_snd_soc_register_card(&pdev->dev, card); From b664e06d530eba6c5f2f1a9571c2bc78e9fb783f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:07:57 +0900 Subject: [PATCH 155/626] ASoC: mediatek: mt2701-wm8960: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-wm8960.c | 34 +++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-wm8960.c b/sound/soc/mediatek/mt2701/mt2701-wm8960.c index 6bc1d3d58e64..8c4c89e4c616 100644 --- a/sound/soc/mediatek/mt2701/mt2701-wm8960.c +++ b/sound/soc/mediatek/mt2701/mt2701-wm8960.c @@ -44,41 +44,51 @@ static struct snd_soc_ops mt2701_wm8960_be_ops = { .hw_params = mt2701_wm8960_be_ops_hw_params }; +SND_SOC_DAILINK_DEFS(playback, + DAILINK_COMP_ARRAY(COMP_CPU("PCMO0")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture, + DAILINK_COMP_ARRAY(COMP_CPU("PCM0")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(codec, + DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8960-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link mt2701_wm8960_dai_links[] = { /* FE */ { .name = "wm8960-playback", .stream_name = "wm8960-playback", - .cpu_dai_name = "PCMO0", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback), }, { .name = "wm8960-capture", .stream_name = "wm8960-capture", - .cpu_dai_name = "PCM0", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture), }, /* BE */ { .name = "wm8960-codec", - .cpu_dai_name = "I2S0", .no_pcm = 1, - .codec_dai_name = "wm8960-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_GATED, .ops = &mt2701_wm8960_be_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(codec), }, }; @@ -107,9 +117,9 @@ static int mt2701_wm8960_machine_probe(struct platform_device *pdev) return -EINVAL; } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } card->dev = &pdev->dev; @@ -122,9 +132,9 @@ static int mt2701_wm8960_machine_probe(struct platform_device *pdev) return -EINVAL; } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->codec_name) + if (dai_link->codecs->name) continue; - dai_link->codec_of_node = codec_node; + dai_link->codecs->of_node = codec_node; } ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); From 4ddabddabf410a261ecbd8177f6e307bdae70d12 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:08:04 +0900 Subject: [PATCH 156/626] ASoC: mediatek: mt2701-cs42448: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-cs42448.c | 95 +++++++++++++++------- 1 file changed, 65 insertions(+), 30 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-cs42448.c b/sound/soc/mediatek/mt2701/mt2701-cs42448.c index 97f9f38ce6b3..b6941796efca 100644 --- a/sound/soc/mediatek/mt2701/mt2701-cs42448.c +++ b/sound/soc/mediatek/mt2701/mt2701-cs42448.c @@ -163,118 +163,153 @@ enum { DAI_LINK_BE_MRG_BT, }; +SND_SOC_DAILINK_DEFS(fe_multi_ch_out, + DAILINK_COMP_ARRAY(COMP_CPU("PCM_multi")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(fe_pcm0_in, + DAILINK_COMP_ARRAY(COMP_CPU("PCM0")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(fe_pcm1_in, + DAILINK_COMP_ARRAY(COMP_CPU("PCM1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(fe_bt_out, + DAILINK_COMP_ARRAY(COMP_CPU("PCM_BT_DL")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(fe_bt_in, + DAILINK_COMP_ARRAY(COMP_CPU("PCM_BT_UL")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(be_i2s0, + DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(be_i2s1, + DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(be_i2s2, + DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(be_i2s3, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(be_mrg_bt, + DAILINK_COMP_ARRAY(COMP_CPU("MRG BT")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "bt-sco-pcm-wb")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = { /* FE */ [DAI_LINK_FE_MULTI_CH_OUT] = { .name = "mt2701-cs42448-multi-ch-out", .stream_name = "mt2701-cs42448-multi-ch-out", - .cpu_dai_name = "PCM_multi", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ops = &mt2701_cs42448_48k_fe_ops, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(fe_multi_ch_out), }, [DAI_LINK_FE_PCM0_IN] = { .name = "mt2701-cs42448-pcm0", .stream_name = "mt2701-cs42448-pcm0-data-UL", - .cpu_dai_name = "PCM0", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ops = &mt2701_cs42448_48k_fe_ops, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(fe_pcm0_in), }, [DAI_LINK_FE_PCM1_IN] = { .name = "mt2701-cs42448-pcm1-data-UL", .stream_name = "mt2701-cs42448-pcm1-data-UL", - .cpu_dai_name = "PCM1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ops = &mt2701_cs42448_48k_fe_ops, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(fe_pcm1_in), }, [DAI_LINK_FE_BT_OUT] = { .name = "mt2701-cs42448-pcm-BT-out", .stream_name = "mt2701-cs42448-pcm-BT", - .cpu_dai_name = "PCM_BT_DL", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(fe_bt_out), }, [DAI_LINK_FE_BT_IN] = { .name = "mt2701-cs42448-pcm-BT-in", .stream_name = "mt2701-cs42448-pcm-BT", - .cpu_dai_name = "PCM_BT_UL", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(fe_bt_in), }, /* BE */ [DAI_LINK_BE_I2S0] = { .name = "mt2701-cs42448-I2S0", - .cpu_dai_name = "I2S0", .no_pcm = 1, - .codec_dai_name = "cs42448", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_GATED, .ops = &mt2701_cs42448_be_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(be_i2s0), }, [DAI_LINK_BE_I2S1] = { .name = "mt2701-cs42448-I2S1", - .cpu_dai_name = "I2S1", .no_pcm = 1, - .codec_dai_name = "cs42448", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_GATED, .ops = &mt2701_cs42448_be_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(be_i2s1), }, [DAI_LINK_BE_I2S2] = { .name = "mt2701-cs42448-I2S2", - .cpu_dai_name = "I2S2", .no_pcm = 1, - .codec_dai_name = "cs42448", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_GATED, .ops = &mt2701_cs42448_be_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(be_i2s2), }, [DAI_LINK_BE_I2S3] = { .name = "mt2701-cs42448-I2S3", - .cpu_dai_name = "I2S3", .no_pcm = 1, - .codec_dai_name = "cs42448", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_GATED, .ops = &mt2701_cs42448_be_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(be_i2s3), }, [DAI_LINK_BE_MRG_BT] = { .name = "mt2701-cs42448-MRG-BT", - .cpu_dai_name = "MRG BT", .no_pcm = 1, - .codec_dai_name = "bt-sco-pcm-wb", .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(be_mrg_bt), }, }; @@ -311,9 +346,9 @@ static int mt2701_cs42448_machine_probe(struct platform_device *pdev) return -EINVAL; } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } card->dev = dev; @@ -326,9 +361,9 @@ static int mt2701_cs42448_machine_probe(struct platform_device *pdev) return -EINVAL; } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->codec_name) + if (dai_link->codecs->name) continue; - dai_link->codec_of_node = codec_node; + dai_link->codecs->of_node = codec_node; } codec_node_bt_mrg = of_parse_phandle(pdev->dev.of_node, @@ -338,7 +373,7 @@ static int mt2701_cs42448_machine_probe(struct platform_device *pdev) "Property 'audio-codec-bt-mrg' missing or invalid\n"); return -EINVAL; } - mt2701_cs42448_dai_links[DAI_LINK_BE_MRG_BT].codec_of_node + mt2701_cs42448_dai_links[DAI_LINK_BE_MRG_BT].codecs->of_node = codec_node_bt_mrg; ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); From 1ea15792bc477e100ac2340b7db3c69c95423d23 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:08:11 +0900 Subject: [PATCH 157/626] ASoC: mediatek: mt8173-max98090: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-max98090.c | 34 +++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c index 4d6596d5cb07..22c00600c999 100644 --- a/sound/soc/mediatek/mt8173/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c @@ -82,41 +82,51 @@ static int mt8173_max98090_init(struct snd_soc_pcm_runtime *runtime) return max98090_mic_detect(component, &mt8173_max98090_jack); } +SND_SOC_DAILINK_DEFS(playback, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture, + DAILINK_COMP_ARRAY(COMP_CPU("VUL")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("I2S")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + /* Digital audio interface glue - connects codec <---> CPU */ static struct snd_soc_dai_link mt8173_max98090_dais[] = { /* Front End DAI links */ { .name = "MAX98090 Playback", .stream_name = "MAX98090 Playback", - .cpu_dai_name = "DL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback), }, { .name = "MAX98090 Capture", .stream_name = "MAX98090 Capture", - .cpu_dai_name = "VUL", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture), }, /* Back End DAI links */ { .name = "Codec", - .cpu_dai_name = "I2S", .no_pcm = 1, - .codec_dai_name = "HiFi", .init = mt8173_max98090_init, .ops = &mt8173_max98090_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(hifi), }, }; @@ -147,9 +157,9 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev) return -EINVAL; } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } codec_node = of_parse_phandle(pdev->dev.of_node, @@ -160,9 +170,9 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev) return -EINVAL; } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->codec_name) + if (dai_link->codecs->name) continue; - dai_link->codec_of_node = codec_node; + dai_link->codecs->of_node = codec_node; } card->dev = &pdev->dev; From 166b3f052d3e6b7afd3759797cbd4e4d5fdaef17 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:08:16 +0900 Subject: [PATCH 158/626] ASoC: mediatek: mt8173-rt5650: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-rt5650.c | 74 +++++++++++++---------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index 7edf250c8fb1..ef6f23675286 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -144,17 +144,6 @@ static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime) &mt8173_rt5650_jack); } -static struct snd_soc_dai_link_component mt8173_rt5650_codecs[] = { - { - /* Playback */ - .dai_name = "rt5645-aif1", - }, - { - /* Capture */ - .dai_name = "rt5645-aif1", - }, -}; - enum { DAI_LINK_PLAYBACK, DAI_LINK_CAPTURE, @@ -163,46 +152,63 @@ enum { DAI_LINK_HDMI_I2S, }; +SND_SOC_DAILINK_DEFS(playback, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture, + DAILINK_COMP_ARRAY(COMP_CPU("VUL")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hdmi_pcm, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(codec, + DAILINK_COMP_ARRAY(COMP_CPU("I2S")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1"), /* Playback */ + COMP_CODEC(NULL, "rt5645-aif1")),/* Capture */ + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hdmi_be, + DAILINK_COMP_ARRAY(COMP_CPU("HDMIO")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + /* Digital audio interface glue - connects codec <---> CPU */ static struct snd_soc_dai_link mt8173_rt5650_dais[] = { /* Front End DAI links */ [DAI_LINK_PLAYBACK] = { .name = "rt5650 Playback", .stream_name = "rt5650 Playback", - .cpu_dai_name = "DL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback), }, [DAI_LINK_CAPTURE] = { .name = "rt5650 Capture", .stream_name = "rt5650 Capture", - .cpu_dai_name = "VUL", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture), }, [DAI_LINK_HDMI] = { .name = "HDMI", .stream_name = "HDMI PCM", - .cpu_dai_name = "HDMI", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(hdmi_pcm), }, /* Back End DAI links */ [DAI_LINK_CODEC_I2S] = { .name = "Codec", - .cpu_dai_name = "I2S", .no_pcm = 1, - .codecs = mt8173_rt5650_codecs, - .num_codecs = 2, .init = mt8173_rt5650_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -210,13 +216,13 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = { .ignore_pmdown_time = 1, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(codec), }, [DAI_LINK_HDMI_I2S] = { .name = "HDMI BE", - .cpu_dai_name = "HDMIO", .no_pcm = 1, - .codec_dai_name = "i2s-hifi", .dpcm_playback = 1, + SND_SOC_DAILINK_REG(hdmi_be), }, }; @@ -250,19 +256,20 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } - mt8173_rt5650_codecs[0].of_node = + mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0); - if (!mt8173_rt5650_codecs[0].of_node) { + if (!mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); return -EINVAL; } - mt8173_rt5650_codecs[1].of_node = mt8173_rt5650_codecs[0].of_node; + mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = + mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node; np = of_get_child_by_name(pdev->dev.of_node, "codec-capture"); if (np) { @@ -274,7 +281,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) __func__, ret); return ret; } - mt8173_rt5650_codecs[1].dai_name = codec_capture_dai; + mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[1].dai_name = + codec_capture_dai; } if (device_property_present(&pdev->dev, "mediatek,mclk")) { @@ -288,9 +296,9 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) } } - mt8173_rt5650_dais[DAI_LINK_HDMI_I2S].codec_of_node = + mt8173_rt5650_dais[DAI_LINK_HDMI_I2S].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); - if (!mt8173_rt5650_dais[DAI_LINK_HDMI_I2S].codec_of_node) { + if (!mt8173_rt5650_dais[DAI_LINK_HDMI_I2S].codecs->of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); return -EINVAL; From 05ab66178cb27ee795aa458b43818d2caa2d3953 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:08:23 +0900 Subject: [PATCH 159/626] ASoC: mediatek: mt8173-rt5650-rt5676: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- .../mediatek/mt8173/mt8173-rt5650-rt5676.c | 85 +++++++++++-------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c index d83cd039b413..9d4dd9721154 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c @@ -111,14 +111,6 @@ static int mt8173_rt5650_rt5676_init(struct snd_soc_pcm_runtime *runtime) &mt8173_rt5650_rt5676_jack); } -static struct snd_soc_dai_link_component mt8173_rt5650_rt5676_codecs[] = { - { - .dai_name = "rt5645-aif1", - }, - { - .dai_name = "rt5677-aif1", - }, -}; enum { DAI_LINK_PLAYBACK, @@ -129,47 +121,69 @@ enum { DAI_LINK_INTERCODEC }; +SND_SOC_DAILINK_DEFS(playback, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture, + DAILINK_COMP_ARRAY(COMP_CPU("VUL")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hdmi_pcm, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(codec, + DAILINK_COMP_ARRAY(COMP_CPU("I2S")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1"), + COMP_CODEC(NULL, "rt5677-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hdmi_be, + DAILINK_COMP_ARRAY(COMP_CPU("HDMIO")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(intercodec, + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5677-aif2")), + DAILINK_COMP_ARRAY(COMP_DUMMY())); + /* Digital audio interface glue - connects codec <---> CPU */ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { /* Front End DAI links */ [DAI_LINK_PLAYBACK] = { .name = "rt5650_rt5676 Playback", .stream_name = "rt5650_rt5676 Playback", - .cpu_dai_name = "DL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback), }, [DAI_LINK_CAPTURE] = { .name = "rt5650_rt5676 Capture", .stream_name = "rt5650_rt5676 Capture", - .cpu_dai_name = "VUL", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture), }, [DAI_LINK_HDMI] = { .name = "HDMI", .stream_name = "HDMI PCM", - .cpu_dai_name = "HDMI", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(hdmi_pcm), }, /* Back End DAI links */ [DAI_LINK_CODEC_I2S] = { .name = "Codec", - .cpu_dai_name = "I2S", .no_pcm = 1, - .codecs = mt8173_rt5650_rt5676_codecs, - .num_codecs = 2, .init = mt8173_rt5650_rt5676_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -177,26 +191,23 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { .ignore_pmdown_time = 1, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(codec), }, [DAI_LINK_HDMI_I2S] = { .name = "HDMI BE", - .cpu_dai_name = "HDMIO", .no_pcm = 1, - .codec_dai_name = "i2s-hifi", .dpcm_playback = 1, + SND_SOC_DAILINK_REG(hdmi_be), }, /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */ [DAI_LINK_INTERCODEC] = { .name = "rt5650_rt5676 intercodec", .stream_name = "rt5650_rt5676 intercodec", - .cpu_dai_name = "snd-soc-dummy-dai", - .platform_name = "snd-soc-dummy", .no_pcm = 1, - .codec_dai_name = "rt5677-aif2", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(intercodec), }, - }; static struct snd_soc_codec_conf mt8173_rt5650_rt5676_codec_conf[] = { @@ -235,34 +246,34 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } - mt8173_rt5650_rt5676_codecs[0].of_node = + mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0); - if (!mt8173_rt5650_rt5676_codecs[0].of_node) { + if (!mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); return -EINVAL; } - mt8173_rt5650_rt5676_codecs[1].of_node = + mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); - if (!mt8173_rt5650_rt5676_codecs[1].of_node) { + if (!mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); return -EINVAL; } mt8173_rt5650_rt5676_codec_conf[0].of_node = - mt8173_rt5650_rt5676_codecs[1].of_node; + mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node; - mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codec_of_node = - mt8173_rt5650_rt5676_codecs[1].of_node; + mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codecs->of_node = + mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node; - mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codec_of_node = + mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 2); - if (!mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codec_of_node) { + if (!mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codecs->of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); return -EINVAL; From 1fcd25641d440495b26518c97fd6e3665a7df135 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:08:38 +0900 Subject: [PATCH 160/626] ASoC: mediatek: mt8173-rt5650-rt5514: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- .../mediatek/mt8173/mt8173-rt5650-rt5514.c | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c index da5b58ce791b..8717e87bfe26 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c @@ -98,51 +98,51 @@ static int mt8173_rt5650_rt5514_init(struct snd_soc_pcm_runtime *runtime) &mt8173_rt5650_rt5514_jack); } -static struct snd_soc_dai_link_component mt8173_rt5650_rt5514_codecs[] = { - { - .dai_name = "rt5645-aif1", - }, - { - .dai_name = "rt5514-aif1", - }, -}; - enum { DAI_LINK_PLAYBACK, DAI_LINK_CAPTURE, DAI_LINK_CODEC_I2S, }; +SND_SOC_DAILINK_DEFS(playback, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture, + DAILINK_COMP_ARRAY(COMP_CPU("VUL")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(codec, + DAILINK_COMP_ARRAY(COMP_CPU("I2S")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1"), + COMP_CODEC(NULL, "rt5514-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + /* Digital audio interface glue - connects codec <---> CPU */ static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = { /* Front End DAI links */ [DAI_LINK_PLAYBACK] = { .name = "rt5650_rt5514 Playback", .stream_name = "rt5650_rt5514 Playback", - .cpu_dai_name = "DL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback), }, [DAI_LINK_CAPTURE] = { .name = "rt5650_rt5514 Capture", .stream_name = "rt5650_rt5514 Capture", - .cpu_dai_name = "VUL", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture), }, /* Back End DAI links */ [DAI_LINK_CODEC_I2S] = { .name = "Codec", - .cpu_dai_name = "I2S", .no_pcm = 1, - .codecs = mt8173_rt5650_rt5514_codecs, - .num_codecs = 2, .init = mt8173_rt5650_rt5514_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -150,6 +150,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = { .ignore_pmdown_time = 1, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(codec), }, }; @@ -189,27 +190,27 @@ static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev) } for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } - mt8173_rt5650_rt5514_codecs[0].of_node = + mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0); - if (!mt8173_rt5650_rt5514_codecs[0].of_node) { + if (!mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); return -EINVAL; } - mt8173_rt5650_rt5514_codecs[1].of_node = + mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); - if (!mt8173_rt5650_rt5514_codecs[1].of_node) { + if (!mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); return -EINVAL; } mt8173_rt5650_rt5514_codec_conf[0].of_node = - mt8173_rt5650_rt5514_codecs[1].of_node; + mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node; card->dev = &pdev->dev; From 4b99064229b426260d6873e865cd9f6732074f6f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:08:43 +0900 Subject: [PATCH 161/626] ASoC: mediatek: mt8183-da7219-max98357: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- .../mediatek/mt8183/mt8183-da7219-max98357.c | 182 ++++++++++-------- 1 file changed, 107 insertions(+), 75 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 231fb49d79b9..59076e21cb47 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -18,18 +18,6 @@ static struct snd_soc_jack headset_jack; -static struct snd_soc_dai_link_component -mt8183_da7219_max98357_external_codecs[] = { - { - .name = "max98357a", - .dai_name = "HiFi", - }, - { - .name = "da7219.5-001a", - .dai_name = "da7219-hifi", - }, -}; - static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -137,191 +125,244 @@ static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = { {"IT6505_8CH", NULL, "TDM"}, }; +/* FE */ +SND_SOC_DAILINK_DEFS(playback1, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback2, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback3, + DAILINK_COMP_ARRAY(COMP_CPU("DL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture1, + DAILINK_COMP_ARRAY(COMP_CPU("UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture2, + DAILINK_COMP_ARRAY(COMP_CPU("UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture3, + DAILINK_COMP_ARRAY(COMP_CPU("UL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture_mono, + DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback_hdmi, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* BE */ +SND_SOC_DAILINK_DEFS(primary_codec, + DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(pcm1, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(pcm2, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s0, + DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), + DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s1, + DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s2, + DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), + DAILINK_COMP_ARRAY(COMP_CODEC("da7219.5-001a", "da7219-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s3, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"), + COMP_CODEC("da7219.5-001a", "da7219-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s5, + DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), + DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(tdm, + DAILINK_COMP_ARRAY(COMP_CPU("TDM")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { /* FE */ { .name = "Playback_1", .stream_name = "Playback_1", - .cpu_dai_name = "DL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback1), }, { .name = "Playback_2", .stream_name = "Playback_2", - .cpu_dai_name = "DL2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback2), }, { .name = "Playback_3", .stream_name = "Playback_3", - .cpu_dai_name = "DL3", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback3), }, { .name = "Capture_1", .stream_name = "Capture_1", - .cpu_dai_name = "UL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture1), }, { .name = "Capture_2", .stream_name = "Capture_2", - .cpu_dai_name = "UL2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture2), }, { .name = "Capture_3", .stream_name = "Capture_3", - .cpu_dai_name = "UL3", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture3), }, { .name = "Capture_Mono_1", .stream_name = "Capture_Mono_1", - .cpu_dai_name = "UL_MONO_1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture_mono), }, { .name = "Playback_HDMI", .stream_name = "Playback_HDMI", - .cpu_dai_name = "HDMI", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback_hdmi), }, /* BE */ { .name = "Primary Codec", - .cpu_dai_name = "ADDA", - .codec_dai_name = "mt6358-snd-codec-aif1", - .codec_name = "mt6358-sound", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(primary_codec), }, { .name = "PCM 1", - .cpu_dai_name = "PCM 1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm1), }, { .name = "PCM 2", - .cpu_dai_name = "PCM 2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm2), }, { .name = "I2S0", - .cpu_dai_name = "I2S0", - .codec_dai_name = "bt-sco-pcm", - .codec_name = "bt-sco", .no_pcm = 1, .dpcm_capture = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_i2s_ops, + SND_SOC_DAILINK_REG(i2s0), }, { .name = "I2S1", - .cpu_dai_name = "I2S1", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_i2s_ops, + SND_SOC_DAILINK_REG(i2s1), }, { .name = "I2S2", - .cpu_dai_name = "I2S2", - .codec_dai_name = "da7219-hifi", - .codec_name = "da7219.5-001a", .no_pcm = 1, .dpcm_capture = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_da7219_i2s_ops, + SND_SOC_DAILINK_REG(i2s2), }, { .name = "I2S3", - .cpu_dai_name = "I2S3", - .codecs = mt8183_da7219_max98357_external_codecs, - .num_codecs = - ARRAY_SIZE(mt8183_da7219_max98357_external_codecs), .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_da7219_i2s_ops, + SND_SOC_DAILINK_REG(i2s3), }, { .name = "I2S5", - .cpu_dai_name = "I2S5", - .codec_dai_name = "bt-sco-pcm", - .codec_name = "bt-sco", .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_i2s_ops, + SND_SOC_DAILINK_REG(i2s5), }, { .name = "TDM", - .cpu_dai_name = "TDM", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(tdm), }, }; @@ -390,18 +431,9 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) } for_each_card_prelinks(card, i, dai_link) { - /* In the alsa soc-core, the "platform" will be - * allocated by devm_kzalloc if null. - * There is a special case that registerring - * sound card is failed at the first time, but - * the "platform" will not null when probe is trying - * again. It's not expected normally. - */ - dai_link->platforms = NULL; - - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } mt8183_da7219_max98357_headset_dev.codec_of_node = From fa284fd002477d5e96bd96f638fbebd65316a750 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:08:49 +0900 Subject: [PATCH 162/626] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- .../mt8183/mt8183-mt6358-ts3a227-max98357.c | 168 +++++++++++------- 1 file changed, 106 insertions(+), 62 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 23c422f13808..887c932229d0 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -96,193 +96,246 @@ static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_bt_sco_ops = { .startup = mt8183_mt6358_ts3a227_max98357_bt_sco_startup, }; +/* FE */ +SND_SOC_DAILINK_DEFS(playback1, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback2, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback3, + DAILINK_COMP_ARRAY(COMP_CPU("DL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture1, + DAILINK_COMP_ARRAY(COMP_CPU("UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture2, + DAILINK_COMP_ARRAY(COMP_CPU("UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture3, + DAILINK_COMP_ARRAY(COMP_CPU("UL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture_mono, + DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback_hdmi, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* BE */ +SND_SOC_DAILINK_DEFS(primary_codec, + DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(pcm1, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(pcm2, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s0, + DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), + DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s1, + DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s2, + DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s3, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s5, + DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), + DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(tdm, + DAILINK_COMP_ARRAY(COMP_CPU("TDM")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link mt8183_mt6358_ts3a227_max98357_dai_links[] = { /* FE */ { .name = "Playback_1", .stream_name = "Playback_1", - .cpu_dai_name = "DL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback1), }, { .name = "Playback_2", .stream_name = "Playback_2", - .cpu_dai_name = "DL2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops, + SND_SOC_DAILINK_REG(playback2), }, { .name = "Playback_3", .stream_name = "Playback_3", - .cpu_dai_name = "DL3", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback3), }, { .name = "Capture_1", .stream_name = "Capture_1", - .cpu_dai_name = "UL1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops, + SND_SOC_DAILINK_REG(capture1), }, { .name = "Capture_2", .stream_name = "Capture_2", - .cpu_dai_name = "UL2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture2), }, { .name = "Capture_3", .stream_name = "Capture_3", - .cpu_dai_name = "UL3", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture3), }, { .name = "Capture_Mono_1", .stream_name = "Capture_Mono_1", - .cpu_dai_name = "UL_MONO_1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture_mono), }, { .name = "Playback_HDMI", .stream_name = "Playback_HDMI", - .cpu_dai_name = "HDMI", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_PRE, SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback_hdmi), }, /* BE */ { .name = "Primary Codec", - .cpu_dai_name = "ADDA", - .codec_dai_name = "mt6358-snd-codec-aif1", - .codec_name = "mt6358-sound", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(primary_codec), }, { .name = "PCM 1", - .cpu_dai_name = "PCM 1", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm1), }, { .name = "PCM 2", - .cpu_dai_name = "PCM 2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .no_pcm = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm2), }, { .name = "I2S0", - .cpu_dai_name = "I2S0", - .codec_dai_name = "bt-sco-pcm", - .codec_name = "bt-sco", .no_pcm = 1, .dpcm_capture = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_i2s_ops, + SND_SOC_DAILINK_REG(i2s0), }, { .name = "I2S1", - .cpu_dai_name = "I2S1", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_i2s_ops, + SND_SOC_DAILINK_REG(i2s1), }, { .name = "I2S2", - .cpu_dai_name = "I2S2", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", .no_pcm = 1, .dpcm_capture = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_i2s_ops, + SND_SOC_DAILINK_REG(i2s2), }, { .name = "I2S3", - .cpu_dai_name = "I2S3", - .codec_dai_name = "HiFi", - .codec_name = "max98357a", .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_i2s_ops, + SND_SOC_DAILINK_REG(i2s3), }, { .name = "I2S5", - .cpu_dai_name = "I2S5", - .codec_dai_name = "bt-sco-pcm", - .codec_name = "bt-sco", .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_i2s_ops, + SND_SOC_DAILINK_REG(i2s5), }, { .name = "TDM", - .cpu_dai_name = "TDM", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(tdm), }, }; @@ -343,18 +396,9 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) } for_each_card_prelinks(card, i, dai_link) { - /* In the alsa soc-core, the "platform" will be - * allocated by devm_kzalloc if null. - * There is a special case that registerring - * sound card is failed at the first time, but - * the "platform" will not null when probe is trying - * again. It's not expected normally. - */ - dai_link->platforms = NULL; - - if (dai_link->platform_name) + if (dai_link->platforms->name) continue; - dai_link->platform_of_node = platform_node; + dai_link->platforms->of_node = platform_node; } mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node = From 5af5e7609af5e1e82bc6fdc617e0b1f5ef3be5e3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:08:55 +0900 Subject: [PATCH 163/626] ASoC: samsung: bells: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/bells.c | 87 ++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 33 deletions(-) diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 770845e2507a..b60b2268b608 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -242,119 +242,140 @@ static const struct snd_soc_pcm_stream sub_params = { .channels_max = 2, }; +SND_SOC_DAILINK_DEFS(wm2200_cpu_dsp, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + +SND_SOC_DAILINK_DEFS(wm2200_dsp_codec, + DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm2200.1-003a", "wm2200"))); + static struct snd_soc_dai_link bells_dai_wm2200[] = { { .name = "CPU-DSP", .stream_name = "CPU-DSP", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm0010-sdi1", - .platform_name = "samsung-i2s.0", - .codec_name = "spi0.0", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(wm2200_cpu_dsp), }, { .name = "DSP-CODEC", .stream_name = "DSP-CODEC", - .cpu_dai_name = "wm0010-sdi2", - .codec_dai_name = "wm2200", - .codec_name = "wm2200.1-003a", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .params = &sub_params, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(wm2200_dsp_codec), }, }; +SND_SOC_DAILINK_DEFS(wm5102_cpu_dsp, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + +SND_SOC_DAILINK_DEFS(wm5102_dsp_codec, + DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1"))); + +SND_SOC_DAILINK_DEFS(wm5102_baseband, + DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1"))); + +SND_SOC_DAILINK_DEFS(wm5102_sub, + DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif3")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi"))); + static struct snd_soc_dai_link bells_dai_wm5102[] = { { .name = "CPU-DSP", .stream_name = "CPU-DSP", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm0010-sdi1", - .platform_name = "samsung-i2s.0", - .codec_name = "spi0.0", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(wm5102_cpu_dsp), }, { .name = "DSP-CODEC", .stream_name = "DSP-CODEC", - .cpu_dai_name = "wm0010-sdi2", - .codec_dai_name = "wm5102-aif1", - .codec_name = "wm5102-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .params = &sub_params, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(wm5102_dsp_codec), }, { .name = "Baseband", .stream_name = "Baseband", - .cpu_dai_name = "wm5102-aif2", - .codec_dai_name = "wm1250-ev1", - .codec_name = "wm1250-ev1.1-0027", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, .params = &baseband_params, + SND_SOC_DAILINK_REG(wm5102_baseband), }, { .name = "Sub", .stream_name = "Sub", - .cpu_dai_name = "wm5102-aif3", - .codec_dai_name = "wm9081-hifi", - .codec_name = "wm9081.1-006c", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, .params = &sub_params, + SND_SOC_DAILINK_REG(wm5102_sub), }, }; +SND_SOC_DAILINK_DEFS(wm5110_cpu_dsp, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + +SND_SOC_DAILINK_DEFS(wm5110_dsp_codec, + DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm5110-codec", "wm5110-aif1"))); + +SND_SOC_DAILINK_DEFS(wm5110_baseband, + DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1"))); + + +SND_SOC_DAILINK_DEFS(wm5110_sub, + DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif3")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi"))); + static struct snd_soc_dai_link bells_dai_wm5110[] = { { .name = "CPU-DSP", .stream_name = "CPU-DSP", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm0010-sdi1", - .platform_name = "samsung-i2s.0", - .codec_name = "spi0.0", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(wm5110_cpu_dsp), }, { .name = "DSP-CODEC", .stream_name = "DSP-CODEC", - .cpu_dai_name = "wm0010-sdi2", - .codec_dai_name = "wm5110-aif1", - .codec_name = "wm5110-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .params = &sub_params, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(wm5110_dsp_codec), }, { .name = "Baseband", .stream_name = "Baseband", - .cpu_dai_name = "wm5110-aif2", - .codec_dai_name = "wm1250-ev1", - .codec_name = "wm1250-ev1.1-0027", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, .params = &baseband_params, + SND_SOC_DAILINK_REG(wm5110_baseband), }, { .name = "Sub", .stream_name = "Sub", - .cpu_dai_name = "wm5110-aif3", - .codec_dai_name = "wm9081-hifi", - .codec_name = "wm9081.1-006c", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, .params = &sub_params, + SND_SOC_DAILINK_REG(wm5110_sub), }, }; From 10601860559d4d2765ff2ccebb3d6a1df4a41c4f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:01 +0900 Subject: [PATCH 164/626] ASoC: samsung: smdk_wm8580: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8580.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index 987807e6f8c3..d096ff912260 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c @@ -140,27 +140,31 @@ enum { #define SMDK_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ SND_SOC_DAIFMT_CBM_CFM) +SND_SOC_DAILINK_DEFS(paif_rx, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8580.0-001b", "wm8580-hifi-playback")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + +SND_SOC_DAILINK_DEFS(paif_tx, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8580.0-001b", "wm8580-hifi-capture")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + static struct snd_soc_dai_link smdk_dai[] = { [PRI_PLAYBACK] = { /* Primary Playback i/f */ .name = "WM8580 PAIF RX", .stream_name = "Playback", - .cpu_dai_name = "samsung-i2s.2", - .codec_dai_name = "wm8580-hifi-playback", - .platform_name = "samsung-i2s.0", - .codec_name = "wm8580.0-001b", .dai_fmt = SMDK_DAI_FMT, .ops = &smdk_ops, + SND_SOC_DAILINK_REG(paif_rx), }, [PRI_CAPTURE] = { /* Primary Capture i/f */ .name = "WM8580 PAIF TX", .stream_name = "Capture", - .cpu_dai_name = "samsung-i2s.2", - .codec_dai_name = "wm8580-hifi-capture", - .platform_name = "samsung-i2s.0", - .codec_name = "wm8580.0-001b", .dai_fmt = SMDK_DAI_FMT, .init = smdk_wm8580_init_paiftx, .ops = &smdk_ops, + SND_SOC_DAILINK_REG(paif_tx), }, }; From 2f8ea84e3a8c9d57a6c893088a3f6145c96d72ee Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:06 +0900 Subject: [PATCH 165/626] ASoC: samsung: smdk_wm8994: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 135d8c2745be..28f8be000aa1 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -100,28 +100,32 @@ static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(aif1, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + +SND_SOC_DAILINK_DEFS(fifo_tx, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s-sec")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s-sec"))); + static struct snd_soc_dai_link smdk_dai[] = { { /* Primary DAI i/f */ .name = "WM8994 AIF1", .stream_name = "Pri_Dai", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm8994-aif1", - .platform_name = "samsung-i2s.0", - .codec_name = "wm8994-codec", .init = smdk_wm8994_init_paiftx, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &smdk_ops, + SND_SOC_DAILINK_REG(aif1), }, { /* Sec_Fifo Playback i/f */ .name = "Sec_FIFO TX", .stream_name = "Sec_Dai", - .cpu_dai_name = "samsung-i2s-sec", - .codec_dai_name = "wm8994-aif1", - .platform_name = "samsung-i2s-sec", - .codec_name = "wm8994-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &smdk_ops, + SND_SOC_DAILINK_REG(fifo_tx), }, }; @@ -153,17 +157,17 @@ static int smdk_audio_probe(struct platform_device *pdev) return -ENOMEM; if (np) { - smdk_dai[0].cpu_dai_name = NULL; - smdk_dai[0].cpu_of_node = of_parse_phandle(np, + smdk_dai[0].cpus->dai_name = NULL; + smdk_dai[0].cpus->of_node = of_parse_phandle(np, "samsung,i2s-controller", 0); - if (!smdk_dai[0].cpu_of_node) { + if (!smdk_dai[0].cpus->of_node) { dev_err(&pdev->dev, "Property 'samsung,i2s-controller' missing or invalid\n"); ret = -EINVAL; } - smdk_dai[0].platform_name = NULL; - smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node; + smdk_dai[0].platforms->name = NULL; + smdk_dai[0].platforms->of_node = smdk_dai[0].cpus->of_node; } id = of_match_device(of_match_ptr(samsung_wm8994_of_match), &pdev->dev); From 245139b2c25c62225577fd7b7a6125bf6f9717d4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:12 +0900 Subject: [PATCH 166/626] ASoC: samsung: smdk_wm8994pcm: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994pcm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index 43171d6457fa..2e3dc7320c62 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -89,17 +89,19 @@ static struct snd_soc_ops smdk_wm8994_pcm_ops = { .hw_params = smdk_wm8994_pcm_hw_params, }; +SND_SOC_DAILINK_DEFS(paif_pcm, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-pcm.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-pcm.0"))); + static struct snd_soc_dai_link smdk_dai[] = { { .name = "WM8994 PAIF PCM", .stream_name = "Primary PCM", - .cpu_dai_name = "samsung-pcm.0", - .codec_dai_name = "wm8994-aif1", - .platform_name = "samsung-pcm.0", - .codec_name = "wm8994-codec", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &smdk_wm8994_pcm_ops, + SND_SOC_DAILINK_REG(paif_pcm), }, }; From e076cc1d9b0567962d48f67fcf5431237ce0ba10 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:19 +0900 Subject: [PATCH 167/626] ASoC: samsung: smdk_spdif: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_spdif.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/smdk_spdif.c b/sound/soc/samsung/smdk_spdif.c index 87a70d872c00..4baef84d29ee 100644 --- a/sound/soc/samsung/smdk_spdif.c +++ b/sound/soc/samsung/smdk_spdif.c @@ -142,14 +142,16 @@ static const struct snd_soc_ops smdk_spdif_ops = { .hw_params = smdk_hw_params, }; +SND_SOC_DAILINK_DEFS(spdif, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-spdif")), + DAILINK_COMP_ARRAY(COMP_CODEC("spdif-dit", "dit-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-spdif"))); + static struct snd_soc_dai_link smdk_dai = { .name = "S/PDIF", .stream_name = "S/PDIF PCM Playback", - .platform_name = "samsung-spdif", - .cpu_dai_name = "samsung-spdif", - .codec_dai_name = "dit-hifi", - .codec_name = "spdif-dit", .ops = &smdk_spdif_ops, + SND_SOC_DAILINK_REG(spdif), }; static struct snd_soc_card smdk = { From 88dd84a196ef69eb33baf555b74687de192f34a5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:25 +0900 Subject: [PATCH 168/626] ASoC: samsung: h1940_uda1380: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/h1940_uda1380.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 95925c4a5964..a95c34e53a2b 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -165,18 +165,20 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) } /* s3c24xx digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(uda1380, + DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")), + DAILINK_COMP_ARRAY(COMP_CODEC("uda1380-codec.0-001a", "uda1380-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis"))); + static struct snd_soc_dai_link h1940_uda1380_dai[] = { { .name = "uda1380", .stream_name = "UDA1380 Duplex", - .cpu_dai_name = "s3c24xx-iis", - .codec_dai_name = "uda1380-hifi", .init = h1940_uda1380_init, - .platform_name = "s3c24xx-iis", - .codec_name = "uda1380-codec.0-001a", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &h1940_ops, + SND_SOC_DAILINK_REG(uda1380), }, }; From 930f74a171f5f3a5acc551568c6a1515344ceef1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:30 +0900 Subject: [PATCH 169/626] ASoC: samsung: arndale_rt5631: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/arndale_rt5631.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/sound/soc/samsung/arndale_rt5631.c b/sound/soc/samsung/arndale_rt5631.c index cc334e1866f6..c213913eb984 100644 --- a/sound/soc/samsung/arndale_rt5631.c +++ b/sound/soc/samsung/arndale_rt5631.c @@ -50,15 +50,20 @@ static struct snd_soc_ops arndale_ops = { .hw_params = arndale_hw_params, }; +SND_SOC_DAILINK_DEFS(rt5631_hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link arndale_rt5631_dai[] = { { .name = "RT5631 HiFi", .stream_name = "Primary", - .codec_dai_name = "rt5631-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &arndale_ops, + SND_SOC_DAILINK_REG(rt5631_hifi), }, }; @@ -78,24 +83,24 @@ static int arndale_audio_probe(struct platform_device *pdev) card->dev = &pdev->dev; for (n = 0; np && n < ARRAY_SIZE(arndale_rt5631_dai); n++) { - if (!arndale_rt5631_dai[n].cpu_dai_name) { - arndale_rt5631_dai[n].cpu_of_node = of_parse_phandle(np, + if (!arndale_rt5631_dai[n].cpus->dai_name) { + arndale_rt5631_dai[n].cpus->of_node = of_parse_phandle(np, "samsung,audio-cpu", n); - if (!arndale_rt5631_dai[n].cpu_of_node) { + if (!arndale_rt5631_dai[n].cpus->of_node) { dev_err(&pdev->dev, "Property 'samsung,audio-cpu' missing or invalid\n"); return -EINVAL; } } - if (!arndale_rt5631_dai[n].platform_name) - arndale_rt5631_dai[n].platform_of_node = - arndale_rt5631_dai[n].cpu_of_node; + if (!arndale_rt5631_dai[n].platforms->name) + arndale_rt5631_dai[n].platforms->of_node = + arndale_rt5631_dai[n].cpus->of_node; - arndale_rt5631_dai[n].codec_name = NULL; - arndale_rt5631_dai[n].codec_of_node = of_parse_phandle(np, + arndale_rt5631_dai[n].codecs->name = NULL; + arndale_rt5631_dai[n].codecs->of_node = of_parse_phandle(np, "samsung,audio-codec", n); - if (!arndale_rt5631_dai[0].codec_of_node) { + if (!arndale_rt5631_dai[0].codecs->of_node) { dev_err(&pdev->dev, "Property 'samsung,audio-codec' missing or invalid\n"); return -EINVAL; From 19bca225e7202710529a14e916a783b1aa42720b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:36 +0900 Subject: [PATCH 170/626] ASoC: samsung: tobermory: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/tobermory.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index 14b11acb12a4..ef51f289fbc7 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -109,17 +109,19 @@ static struct snd_soc_ops tobermory_ops = { .hw_params = tobermory_hw_params, }; +SND_SOC_DAILINK_DEFS(cpu, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8962.1-001a", "wm8962")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + static struct snd_soc_dai_link tobermory_dai[] = { { .name = "CPU", .stream_name = "CPU", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm8962", - .platform_name = "samsung-i2s.0", - .codec_name = "wm8962.1-001a", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &tobermory_ops, + SND_SOC_DAILINK_REG(cpu), }, }; From f1d26f2b947ea6cc3265b0e3c0a265c57a43f945 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:44 +0900 Subject: [PATCH 171/626] ASoC: samsung: tm2_wm5110: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/tm2_wm5110.c | 42 ++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 31f4256c6c65..c091033d17ad 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -427,38 +427,56 @@ static struct snd_soc_dai_driver tm2_ext_dai[] = { }, }; +SND_SOC_DAILINK_DEFS(aif1, + DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(voice, + DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif2")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(bt, + DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif3")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hdmi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tm2_dai_links[] = { { .name = "WM5110 AIF1", .stream_name = "HiFi Primary", - .cpu_dai_name = SAMSUNG_I2S_DAI, - .codec_dai_name = "wm5110-aif1", .ops = &tm2_aif1_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(aif1), }, { .name = "WM5110 Voice", .stream_name = "Voice call", - .cpu_dai_name = SAMSUNG_I2S_DAI, - .codec_dai_name = "wm5110-aif2", .ops = &tm2_aif2_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(voice), }, { .name = "WM5110 BT", .stream_name = "Bluetooth", - .cpu_dai_name = SAMSUNG_I2S_DAI, - .codec_dai_name = "wm5110-aif3", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(bt), }, { .name = "HDMI", .stream_name = "i2s1", .ops = &tm2_hdmi_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(hdmi), } }; @@ -557,15 +575,15 @@ static int tm2_probe(struct platform_device *pdev) for_each_card_prelinks(card, i, dai_link) { unsigned int dai_index = 0; /* WM5110 */ - dai_link->cpu_name = NULL; - dai_link->platform_name = NULL; + dai_link->cpus->name = NULL; + dai_link->platforms->name = NULL; if (num_codecs > 1 && i == card->num_links - 1) dai_index = 1; /* HDMI */ - dai_link->codec_of_node = codec_dai_node[dai_index]; - dai_link->cpu_of_node = cpu_dai_node[dai_index]; - dai_link->platform_of_node = cpu_dai_node[dai_index]; + dai_link->codecs->of_node = codec_dai_node[dai_index]; + dai_link->cpus->of_node = cpu_dai_node[dai_index]; + dai_link->platforms->of_node = cpu_dai_node[dai_index]; } if (num_codecs > 1) { @@ -579,7 +597,7 @@ static int tm2_probe(struct platform_device *pdev) goto dai_node_put; } - ret = snd_soc_get_dai_name(&args, &card->dai_link[i].codec_dai_name); + ret = snd_soc_get_dai_name(&args, &card->dai_link[i].codecs->dai_name); if (ret) { dev_err(dev, "Unable to get codec_dai_name\n"); goto dai_node_put; From 3f60911771a10a8f87e56e61deb501a054c2ea0c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:50 +0900 Subject: [PATCH 172/626] ASoC: samsung: speyside: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/speyside.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 15465c84daa3..51e4c976c8be 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -189,39 +189,45 @@ static const struct snd_soc_pcm_stream dsp_codec_params = { .channels_max = 2, }; +SND_SOC_DAILINK_DEFS(cpu_dsp, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + +SND_SOC_DAILINK_DEFS(dsp_codec, + DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8996.1-001a", "wm8996-aif1"))); + +SND_SOC_DAILINK_DEFS(baseband, + DAILINK_COMP_ARRAY(COMP_CPU("wm8996-aif2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1"))); + static struct snd_soc_dai_link speyside_dai[] = { { .name = "CPU-DSP", .stream_name = "CPU-DSP", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm0010-sdi1", - .platform_name = "samsung-i2s.0", - .codec_name = "spi0.0", .init = speyside_wm0010_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(cpu_dsp), }, { .name = "DSP-CODEC", .stream_name = "DSP-CODEC", - .cpu_dai_name = "wm0010-sdi2", - .codec_dai_name = "wm8996-aif1", - .codec_name = "wm8996.1-001a", .init = speyside_wm8996_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .params = &dsp_codec_params, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(dsp_codec), }, { .name = "Baseband", .stream_name = "Baseband", - .cpu_dai_name = "wm8996-aif2", - .codec_dai_name = "wm1250-ev1", - .codec_name = "wm1250-ev1.1-0027", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(baseband), }, }; From db1623faa43264fe4ef2234cdc555c0623b77482 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:09:56 +0900 Subject: [PATCH 173/626] ASoC: samsung: snow: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 57ce90fe5004..8ea7799df028 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -14,6 +14,11 @@ #define FIN_PLL_RATE 24000000 +SND_SOC_DAILINK_DEFS(links, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + struct snow_priv { struct snd_soc_dai_link dai_link; struct clk *clk_i2s_bus; @@ -141,6 +146,13 @@ static int snow_probe(struct platform_device *pdev) link->name = "Primary"; link->stream_name = link->name; + link->cpus = links_cpus; + link->num_cpus = ARRAY_SIZE(links_cpus); + link->codecs = links_codecs; + link->num_codecs = ARRAY_SIZE(links_codecs); + link->platforms = links_platforms; + link->num_platforms = ARRAY_SIZE(links_platforms); + card->dai_link = link; card->num_links = 1; card->dev = dev; @@ -151,10 +163,10 @@ static int snow_probe(struct platform_device *pdev) if (cpu) { link->ops = &snow_card_ops; - link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); + link->cpus->of_node = of_parse_phandle(cpu, "sound-dai", 0); of_node_put(cpu); - if (!link->cpu_of_node) { + if (!link->cpus->of_node) { dev_err(dev, "Failed parsing cpu/sound-dai property\n"); return -EINVAL; } @@ -164,38 +176,38 @@ static int snow_probe(struct platform_device *pdev) of_node_put(codec); if (ret < 0) { - of_node_put(link->cpu_of_node); + of_node_put(link->cpus->of_node); dev_err(dev, "Failed parsing codec node\n"); return ret; } - priv->clk_i2s_bus = of_clk_get_by_name(link->cpu_of_node, + priv->clk_i2s_bus = of_clk_get_by_name(link->cpus->of_node, "i2s_opclk0"); if (IS_ERR(priv->clk_i2s_bus)) { snd_soc_of_put_dai_link_codecs(link); - of_node_put(link->cpu_of_node); + of_node_put(link->cpus->of_node); return PTR_ERR(priv->clk_i2s_bus); } } else { - link->codec_dai_name = "HiFi", + link->codecs->dai_name = "HiFi", - link->cpu_of_node = of_parse_phandle(dev->of_node, + link->cpus->of_node = of_parse_phandle(dev->of_node, "samsung,i2s-controller", 0); - if (!link->cpu_of_node) { + if (!link->cpus->of_node) { dev_err(dev, "i2s-controller property parse error\n"); return -EINVAL; } - link->codec_of_node = of_parse_phandle(dev->of_node, + link->codecs->of_node = of_parse_phandle(dev->of_node, "samsung,audio-codec", 0); - if (!link->codec_of_node) { - of_node_put(link->cpu_of_node); + if (!link->codecs->of_node) { + of_node_put(link->cpus->of_node); dev_err(dev, "audio-codec property parse error\n"); return -EINVAL; } } - link->platform_of_node = link->cpu_of_node; + link->platforms->of_node = link->cpus->of_node; /* Update card-name if provided through DT, else use default name */ snd_soc_of_parse_card_name(card, "samsung,model"); @@ -216,8 +228,8 @@ static int snow_remove(struct platform_device *pdev) struct snow_priv *priv = platform_get_drvdata(pdev); struct snd_soc_dai_link *link = &priv->dai_link; - of_node_put(link->cpu_of_node); - of_node_put(link->codec_of_node); + of_node_put(link->cpus->of_node); + of_node_put(link->codecs->of_node); snd_soc_of_put_dai_link_codecs(link); clk_put(priv->clk_i2s_bus); From a259926056dde250bcb34f015dd9eb72d4709b69 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:01 +0900 Subject: [PATCH 174/626] ASoC: samsung: smartq_wm8987: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/smartq_wm8987.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index b9e887ea60b2..fab3db9fdb98 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c @@ -153,18 +153,20 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd) return err; } +SND_SOC_DAILINK_DEFS(wm8987, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8750.0-0x1a", "wm8750-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + static struct snd_soc_dai_link smartq_dai[] = { { .name = "wm8987", .stream_name = "SmartQ Hi-Fi", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm8750-hifi", - .platform_name = "samsung-i2s.0", - .codec_name = "wm8750.0-0x1a", .init = smartq_wm8987_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &smartq_hifi_ops, + SND_SOC_DAILINK_REG(wm8987), }, }; From bb5e4a032488f6257fc9cb942dbbd06e2e9af226 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:06 +0900 Subject: [PATCH 175/626] ASoC: samsung: s3c24xx_uda134x: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx_uda134x.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 9d68f8ca1fcc..55d2a802a6cb 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -201,16 +201,18 @@ static const struct snd_soc_ops s3c24xx_uda134x_ops = { .hw_params = s3c24xx_uda134x_hw_params, }; +SND_SOC_DAILINK_DEFS(uda134x, + DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")), + DAILINK_COMP_ARRAY(COMP_CODEC("uda134x-codec", "uda134x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis"))); + static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { .name = "UDA134X", .stream_name = "UDA134X", - .codec_name = "uda134x-codec", - .codec_dai_name = "uda134x-hifi", - .cpu_dai_name = "s3c24xx-iis", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &s3c24xx_uda134x_ops, - .platform_name = "s3c24xx-iis", + SND_SOC_DAILINK_REG(uda134x), }; static struct snd_soc_card snd_soc_s3c24xx_uda134x = { From fba1384c3bff25de469a9dcb970a27669e540f42 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:11 +0900 Subject: [PATCH 176/626] ASoC: samsung: s3c24xx_simtec_tlv320aic23: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c index 1360b881400d..c03d52990267 100644 --- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c +++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c @@ -52,14 +52,17 @@ static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(tlv320aic23, + DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.0-001a", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis"))); + static struct snd_soc_dai_link simtec_dai_aic23 = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", - .codec_name = "tlv320aic3x-codec.0-001a", - .cpu_dai_name = "s3c24xx-iis", - .codec_dai_name = "tlv320aic3x-hifi", - .platform_name = "s3c24xx-iis", .init = simtec_tlv320aic23_init, + SND_SOC_DAILINK_REG(tlv320aic23), }; /* simtec audio machine driver */ From 1c0f3edbcabd014b70473937199467af3e1339c5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:16 +0900 Subject: [PATCH 177/626] ASoC: samsung: s3c24xx_simtec_hermes: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx_simtec_hermes.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c index e3528e74a338..ed0d1b8fa2d4 100644 --- a/sound/soc/samsung/s3c24xx_simtec_hermes.c +++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c @@ -63,14 +63,17 @@ static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(tlv320aic33, + DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.0-001a", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis"))); + static struct snd_soc_dai_link simtec_dai_aic33 = { .name = "tlv320aic33", .stream_name = "TLV320AIC33", - .codec_name = "tlv320aic3x-codec.0-001a", - .cpu_dai_name = "s3c24xx-iis", - .codec_dai_name = "tlv320aic3x-hifi", - .platform_name = "s3c24xx-iis", .init = simtec_hermes_init, + SND_SOC_DAILINK_REG(tlv320aic33), }; /* simtec audio machine driver */ From 400127a12ae36fe61e2740a96c7bad4755c43d65 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:21 +0900 Subject: [PATCH 178/626] ASoC: samsung: rx1950_uda1380: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/rx1950_uda1380.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 1dcc1b252ad1..4b247e91ae5b 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -72,18 +72,21 @@ static struct snd_soc_ops rx1950_ops = { }; /* s3c24xx digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(uda1380, + DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")), + DAILINK_COMP_ARRAY(COMP_CODEC("uda1380-codec.0-001a", + "uda1380-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis"))); + static struct snd_soc_dai_link rx1950_uda1380_dai[] = { { .name = "uda1380", .stream_name = "UDA1380 Duplex", - .cpu_dai_name = "s3c24xx-iis", - .codec_dai_name = "uda1380-hifi", .init = rx1950_uda1380_init, - .platform_name = "s3c24xx-iis", - .codec_name = "uda1380-codec.0-001a", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &rx1950_ops, + SND_SOC_DAILINK_REG(uda1380), }, }; From 3cddda10c25f4627a43f3db9314a9c79c5a60ce1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:26 +0900 Subject: [PATCH 179/626] ASoC: samsung: odroid: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/odroid.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index e688169ff12a..dfb6e460e7eb 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -151,39 +151,48 @@ static const struct snd_soc_dapm_route odroid_dapm_routes[] = { { "HiFi Playback", NULL, "Mixer DAI TX" }, }; +SND_SOC_DAILINK_DEFS(primary, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_PLATFORM("3830000.i2s"))); + +SND_SOC_DAILINK_DEFS(mixer, + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEFS(secondary, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_PLATFORM("3830000.i2s-sec"))); + static struct snd_soc_dai_link odroid_card_dais[] = { { /* Primary FE <-> BE link */ - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .ops = &odroid_card_fe_ops, .name = "Primary", .stream_name = "Primary", - .platform_name = "3830000.i2s", .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(primary), }, { /* BE <-> CODECs link */ .name = "I2S Mixer", - .cpu_name = "snd-soc-dummy", - .cpu_dai_name = "snd-soc-dummy-dai", - .platform_name = "snd-soc-dummy", .ops = &odroid_card_be_ops, .no_pcm = 1, .dpcm_playback = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(mixer), }, { /* Secondary FE <-> BE link */ .playback_only = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .ops = &odroid_card_fe_ops, .name = "Secondary", .stream_name = "Secondary", - .platform_name = "3830000.i2s-sec", .dynamic = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(secondary), } }; @@ -262,7 +271,7 @@ static int odroid_audio_probe(struct platform_device *pdev) break; } - ret = snd_soc_get_dai_name(&args, &link->cpu_dai_name); + ret = snd_soc_get_dai_name(&args, &link->cpus->dai_name); of_node_put(args.np); if (ret < 0) From 0391b03374ceb8a4f40e13e1c5780d694488228d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:32 +0900 Subject: [PATCH 180/626] ASoC: samsung: neo1973_wm8753: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/neo1973_wm8753.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 7e625066ddcd..396776ffd670 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -266,28 +266,32 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(wm8753, + DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8753.0-001a", "wm8753-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis"))); + +SND_SOC_DAILINK_DEFS(bluetooth, + DAILINK_COMP_ARRAY(COMP_CPU("bt-sco-pcm")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8753.0-001a", "wm8753-voice"))); + static struct snd_soc_dai_link neo1973_dai[] = { { /* Hifi Playback - for similatious use with voice below */ .name = "WM8753", .stream_name = "WM8753 HiFi", - .platform_name = "s3c24xx-iis", - .cpu_dai_name = "s3c24xx-iis", - .codec_dai_name = "wm8753-hifi", - .codec_name = "wm8753.0-001a", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .init = neo1973_wm8753_init, .ops = &neo1973_hifi_ops, + SND_SOC_DAILINK_REG(wm8753), }, { /* Voice via BT */ .name = "Bluetooth", .stream_name = "Voice", - .cpu_dai_name = "bt-sco-pcm", - .codec_dai_name = "wm8753-voice", - .codec_name = "wm8753.0-001a", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &neo1973_voice_ops, + SND_SOC_DAILINK_REG(bluetooth), }, }; From 7989919453afbaa997a848285ee1a3b940f11e4d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:36 +0900 Subject: [PATCH 181/626] ASoC: samsung: lowland: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/lowland.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index 2fdab2ac8e8c..973f22bcc747 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c @@ -82,39 +82,45 @@ static const struct snd_soc_pcm_stream sub_params = { .channels_max = 2, }; +SND_SOC_DAILINK_DEFS(cpu, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm5100.1-001a", "wm5100-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + +SND_SOC_DAILINK_DEFS(baseband, + DAILINK_COMP_ARRAY(COMP_CPU("wm5100-aif2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1"))); + +SND_SOC_DAILINK_DEFS(speaker, + DAILINK_COMP_ARRAY(COMP_CPU("wm5100-aif3")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi"))); + static struct snd_soc_dai_link lowland_dai[] = { { .name = "CPU", .stream_name = "CPU", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm5100-aif1", - .platform_name = "samsung-i2s.0", - .codec_name = "wm5100.1-001a", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .init = lowland_wm5100_init, + SND_SOC_DAILINK_REG(cpu), }, { .name = "Baseband", .stream_name = "Baseband", - .cpu_dai_name = "wm5100-aif2", - .codec_dai_name = "wm1250-ev1", - .codec_name = "wm1250-ev1.1-0027", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, + SND_SOC_DAILINK_REG(baseband), }, { .name = "Sub Speaker", .stream_name = "Sub Speaker", - .cpu_dai_name = "wm5100-aif3", - .codec_dai_name = "wm9081-hifi", - .codec_name = "wm9081.1-006c", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, .params = &sub_params, .init = lowland_wm9081_init, + SND_SOC_DAILINK_REG(speaker), }, }; From e28d6e02889c7448b470e55ea8440b65fd2ddf75 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:41 +0900 Subject: [PATCH 182/626] ASoC: samsung: littlemill: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/littlemill.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index cd70b06cc99d..6132cee8550b 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -142,28 +142,33 @@ static const struct snd_soc_pcm_stream baseband_params = { .channels_max = 2, }; +SND_SOC_DAILINK_DEFS(cpu, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + +SND_SOC_DAILINK_DEFS(baseband, + DAILINK_COMP_ARRAY(COMP_CPU("wm8994-aif2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", + "wm1250-ev1"))); + static struct snd_soc_dai_link littlemill_dai[] = { { .name = "CPU", .stream_name = "CPU", - .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm8994-aif1", - .platform_name = "samsung-i2s.0", - .codec_name = "wm8994-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &littlemill_ops, + SND_SOC_DAILINK_REG(cpu), }, { .name = "Baseband", .stream_name = "Baseband", - .cpu_dai_name = "wm8994-aif2", - .codec_dai_name = "wm1250-ev1", - .codec_name = "wm1250-ev1.1-0027", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, .params = &baseband_params, + SND_SOC_DAILINK_REG(baseband), }, }; From 9423082951be26bd60d9fc1133d2ea9014aade6b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:46 +0900 Subject: [PATCH 183/626] ASoC: samsung: jive_wm8750: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/jive_wm8750.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index f05f9e03f07d..949d2e029962 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c @@ -78,16 +78,18 @@ static const struct snd_soc_ops jive_ops = { .hw_params = jive_hw_params, }; +SND_SOC_DAILINK_DEFS(wm8750, + DAILINK_COMP_ARRAY(COMP_CPU("s3c2412-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8750.0-001a", "wm8750-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c2412-i2s"))); + static struct snd_soc_dai_link jive_dai = { .name = "wm8750", .stream_name = "WM8750", - .cpu_dai_name = "s3c2412-i2s", - .codec_dai_name = "wm8750-hifi", - .platform_name = "s3c2412-i2s", - .codec_name = "wm8750.0-001a", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &jive_ops, + SND_SOC_DAILINK_REG(wm8750), }; /* jive audio machine driver */ From b63eec7443b16c760ee76a887ed3b715a163580e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:51 +0900 Subject: [PATCH 184/626] ASoC: pxa: brownstone: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/brownstone.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c index 9a3f5b799720..38ea26cfc7c8 100644 --- a/sound/soc/pxa/brownstone.c +++ b/sound/soc/pxa/brownstone.c @@ -78,17 +78,19 @@ static const struct snd_soc_ops brownstone_ops = { .hw_params = brownstone_wm8994_hw_params, }; +SND_SOC_DAILINK_DEFS(wm8994, + DAILINK_COMP_ARRAY(COMP_CPU("mmp-sspa-dai.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("mmp-pcm-audio"))); + static struct snd_soc_dai_link brownstone_wm8994_dai[] = { { .name = "WM8994", .stream_name = "WM8994 HiFi", - .cpu_dai_name = "mmp-sspa-dai.0", - .codec_dai_name = "wm8994-aif1", - .platform_name = "mmp-pcm-audio", - .codec_name = "wm8994-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &brownstone_ops, + SND_SOC_DAILINK_REG(wm8994), }, }; From 432895f4f6d916eed93a6e434adc3c67655de2d2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:10:56 +0900 Subject: [PATCH 185/626] ASoC: pxa: corgi: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 054e0d65db9d..dae128833692 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -260,16 +260,18 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = { }; /* corgi digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(wm8731, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link corgi_dai = { .name = "WM8731", .stream_name = "WM8731", - .cpu_dai_name = "pxa2xx-i2s", - .codec_dai_name = "wm8731-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm8731.0-001b", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &corgi_ops, + SND_SOC_DAILINK_REG(wm8731), }; /* corgi audio machine driver */ From 312989a1ed69564bf6b9d329ce60e39c8487c32a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:11:01 +0900 Subject: [PATCH 186/626] ASoC: pxa: e740_wm9705: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/e740_wm9705.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 8ab7032631b7..15141a89c9ba 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -84,22 +84,26 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Mic Amp", NULL, "Mic (Internal)"}, }; +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9705-codec", "wm9705-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(ac97_aux, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9705-codec", "wm9705-aux")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link e740_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "pxa2xx-ac97", - .codec_dai_name = "wm9705-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9705-codec", + SND_SOC_DAILINK_REG(ac97), }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai_name = "pxa2xx-ac97-aux", - .codec_dai_name = "wm9705-aux", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9705-codec", + SND_SOC_DAILINK_REG(ac97_aux), }, }; From f78ced5147dc8dd64053bb905787c332bc195543 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:11:06 +0900 Subject: [PATCH 187/626] ASoC: pxa: e750_wm9705: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/e750_wm9705.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 82bcbbb1841b..406ecf2a822f 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -67,23 +67,27 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC1", NULL, "Mic (Internal)"}, }; +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9705-codec", "wm9705-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(ac97_aux, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9705-codec", "wm9705-aux")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link e750_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "pxa2xx-ac97", - .codec_dai_name = "wm9705-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9705-codec", + SND_SOC_DAILINK_REG(ac97), /* use ops to check startup state */ }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai_name = "pxa2xx-ac97-aux", - .codec_dai_name = "wm9705-aux", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9705-codec", + SND_SOC_DAILINK_REG(ac97_aux), }, }; From 32b787a0ce77221f809b42b4cb21b176a0422068 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:11:12 +0900 Subject: [PATCH 188/626] ASoC: pxa: e800_wm9712: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/e800_wm9712.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 1ed8aa2348f1..fc3aa3d77c75 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -68,22 +68,27 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC2", NULL, "Mic (Internal2)"}, }; + +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(ac97_aux, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link e800_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "pxa2xx-ac97", - .codec_dai_name = "wm9712-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9712-codec", + SND_SOC_DAILINK_REG(ac97), }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai_name = "pxa2xx-ac97-aux", - .codec_dai_name = "wm9712-aux", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9712-codec", + SND_SOC_DAILINK_REG(ac97_aux), }, }; From d7d8e1b14c165fc4c32037521af736669c454e02 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:11:18 +0900 Subject: [PATCH 189/626] ASoC: pxa: em-x270: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/em-x270.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index e046770ce70e..9ff2a64e0981 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c @@ -30,22 +30,26 @@ #include #include +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(ac97_aux, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link em_x270_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "pxa2xx-ac97", - .codec_dai_name = "wm9712-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9712-codec", + SND_SOC_DAILINK_REG(ac97), }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai_name = "pxa2xx-ac97-aux", - .codec_dai_name = "wm9712-aux", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9712-codec", + SND_SOC_DAILINK_REG(ac97_aux), }, }; From 08baa54ee7d15981aaa4176abd04a6d4206920cb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:11:41 +0900 Subject: [PATCH 190/626] ASoC: pxa: hx4700: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/hx4700.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c index 6cdef5d4954e..5d86e61c4f6a 100644 --- a/sound/soc/pxa/hx4700.c +++ b/sound/soc/pxa/hx4700.c @@ -139,17 +139,19 @@ static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd) } /* hx4700 digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(ak4641, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("ak4641.0-0012", "ak4641-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link hx4700_dai = { .name = "ak4641", .stream_name = "AK4641", - .cpu_dai_name = "pxa2xx-i2s", - .codec_dai_name = "ak4641-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "ak4641.0-0012", .init = hx4700_ak4641_init, .dai_fmt = SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &hx4700_ops, + SND_SOC_DAILINK_REG(ak4641), }; /* hx4700 audio machine driver */ From 76359b17c38d513743a151b3cf747a5867dd6216 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:11:46 +0900 Subject: [PATCH 191/626] ASoC: pxa: imote2: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/imote2.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c index 78475376f971..9095edd6a374 100644 --- a/sound/soc/pxa/imote2.c +++ b/sound/soc/pxa/imote2.c @@ -46,16 +46,19 @@ static const struct snd_soc_ops imote2_asoc_ops = { .hw_params = imote2_asoc_hw_params, }; +SND_SOC_DAILINK_DEFS(wm8940, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8940-codec.0-0034", + "wm8940-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link imote2_dai = { .name = "WM8940", .stream_name = "WM8940", - .cpu_dai_name = "pxa2xx-i2s", - .codec_dai_name = "wm8940-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm8940-codec.0-0034", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &imote2_asoc_ops, + SND_SOC_DAILINK_REG(wm8940), }; static struct snd_soc_card imote2 = { From 018252749ce4cf683ad5164fe47ca00d5c567234 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:11:51 +0900 Subject: [PATCH 192/626] ASoC: pxa: magician: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/magician.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 935a248e5bf6..bf8084f2e625 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -290,24 +290,30 @@ static const struct snd_kcontrol_new uda1380_magician_controls[] = { }; /* magician digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(playback, + DAILINK_COMP_ARRAY(COMP_CPU("pxa-ssp-dai.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("uda1380-codec.0-0018", + "uda1380-hifi-playback")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(capture, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("uda1380-codec.0-0018", + "uda1380-hifi-capture")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link magician_dai[] = { { .name = "uda1380", .stream_name = "UDA1380 Playback", - .cpu_dai_name = "pxa-ssp-dai.0", - .codec_dai_name = "uda1380-hifi-playback", - .platform_name = "pxa-pcm-audio", - .codec_name = "uda1380-codec.0-0018", .ops = &magician_playback_ops, + SND_SOC_DAILINK_REG(playback), }, { .name = "uda1380", .stream_name = "UDA1380 Capture", - .cpu_dai_name = "pxa2xx-i2s", - .codec_dai_name = "uda1380-hifi-capture", - .platform_name = "pxa-pcm-audio", - .codec_name = "uda1380-codec.0-0018", .ops = &magician_capture_ops, + SND_SOC_DAILINK_REG(capture), } }; From a94112f5bd0b4b05ba727491c3d96dfb4c702823 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:11:56 +0900 Subject: [PATCH 193/626] ASoC: pxa: mioa701_wm9713: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/mioa701_wm9713.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 47052fe3f5f4..6244e5caddbe 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -142,25 +142,29 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_ops mioa701_ops; +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(ac97_aux, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-aux")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link mioa701_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "pxa2xx-ac97", - .codec_dai_name = "wm9713-hifi", - .codec_name = "wm9713-codec", .init = mioa701_wm9713_init, - .platform_name = "pxa-pcm-audio", .ops = &mioa701_ops, + SND_SOC_DAILINK_REG(ac97), }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai_name = "pxa2xx-ac97-aux", - .codec_dai_name = "wm9713-aux", - .codec_name = "wm9713-codec", - .platform_name = "pxa-pcm-audio", .ops = &mioa701_ops, + SND_SOC_DAILINK_REG(ac97_aux), }, }; From ef15331de2e4e660361b3a72569011793d3a3d9c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:01 +0900 Subject: [PATCH 194/626] ASoC: pxa: palm27x: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/palm27x.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 97167048572d..d973f9ba9fd7 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -87,23 +87,27 @@ static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd) return err; } +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(aux, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link palm27x_dai[] = { { .name = "AC97 HiFi", .stream_name = "AC97 HiFi", - .cpu_dai_name = "pxa2xx-ac97", - .codec_dai_name = "wm9712-hifi", - .codec_name = "wm9712-codec", - .platform_name = "pxa-pcm-audio", .init = palm27x_ac97_init, + SND_SOC_DAILINK_REG(hifi), }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai_name = "pxa2xx-ac97-aux", - .codec_dai_name = "wm9712-aux", - .codec_name = "wm9712-codec", - .platform_name = "pxa-pcm-audio", + SND_SOC_DAILINK_REG(aux), }, }; From 1129efb0a390c7f00a4e0b70ddc4c8d4860ead39 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:06 +0900 Subject: [PATCH 195/626] ASoC: pxa: zylonite: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 230eee450f45..ac7d05201772 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -127,34 +127,40 @@ static const struct snd_soc_ops zylonite_voice_ops = { .hw_params = zylonite_voice_hw_params, }; +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(ac97_aux, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-aux")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(voice, + DAILINK_COMP_ARRAY(COMP_CPU("pxa-ssp-dai.2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-voice")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link zylonite_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .codec_name = "wm9713-codec", - .platform_name = "pxa-pcm-audio", - .cpu_dai_name = "pxa2xx-ac97", - .codec_dai_name = "wm9713-hifi", .init = zylonite_wm9713_init, + SND_SOC_DAILINK_REG(ac97), }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .codec_name = "wm9713-codec", - .platform_name = "pxa-pcm-audio", - .cpu_dai_name = "pxa2xx-ac97-aux", - .codec_dai_name = "wm9713-aux", + SND_SOC_DAILINK_REG(ac97_aux), }, { .name = "WM9713 Voice", .stream_name = "WM9713 Voice", - .codec_name = "wm9713-codec", - .platform_name = "pxa-pcm-audio", - .cpu_dai_name = "pxa-ssp-dai.2", - .codec_dai_name = "wm9713-voice", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &zylonite_voice_ops, + SND_SOC_DAILINK_REG(voice), }, }; From dca012bb860239f90931f5943f4a3e6a4c1ddad3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:11 +0900 Subject: [PATCH 196/626] ASoC: pxa: z2: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/z2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index 5b0eccd2b4dd..40d34b911774 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c @@ -157,17 +157,19 @@ static const struct snd_soc_ops z2_ops = { }; /* z2 digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(wm8750, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8750.0-001b", "wm8750-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link z2_dai = { .name = "wm8750", .stream_name = "WM8750", - .cpu_dai_name = "pxa2xx-i2s", - .codec_dai_name = "wm8750-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm8750.0-001b", .init = z2_wm8750_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &z2_ops, + SND_SOC_DAILINK_REG(wm8750), }; /* z2 audio machine driver */ From 0d246384cae61ad45940cacf3960bed29f1cd30c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:16 +0900 Subject: [PATCH 197/626] ASoC: pxa: ttc-dkb: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/ttc-dkb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c index 5d6e61a4bb7e..5a13e36a2499 100644 --- a/sound/soc/pxa/ttc-dkb.c +++ b/sound/soc/pxa/ttc-dkb.c @@ -94,17 +94,19 @@ static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd) } /* ttc/td-dkb digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(i2s, + DAILINK_COMP_ARRAY(COMP_CPU("pxa-ssp-dai.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("88pm860x-codec", "88pm860x-i2s")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("mmp-pcm-audio"))); + static struct snd_soc_dai_link ttc_pm860x_hifi_dai[] = { { .name = "88pm860x i2s", .stream_name = "audio playback", - .codec_name = "88pm860x-codec", - .platform_name = "mmp-pcm-audio", - .cpu_dai_name = "pxa-ssp-dai.1", - .codec_dai_name = "88pm860x-i2s", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .init = ttc_pm860x_init, + SND_SOC_DAILINK_REG(i2s), }, }; From cc7b2401cd93a884813af224cc24c8d8f31f39cd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:20 +0900 Subject: [PATCH 198/626] ASoC: pxa: tosa: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/tosa.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index ae9c12e1ea2a..e7cb450d9e8a 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -182,24 +182,28 @@ static const struct snd_kcontrol_new tosa_controls[] = { tosa_set_spk), }; +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(ac97_aux, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link tosa_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "pxa2xx-ac97", - .codec_dai_name = "wm9712-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9712-codec", .ops = &tosa_ops, + SND_SOC_DAILINK_REG(ac97), }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai_name = "pxa2xx-ac97-aux", - .codec_dai_name = "wm9712-aux", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm9712-codec", .ops = &tosa_ops, + SND_SOC_DAILINK_REG(ac97_aux), }, }; From 196a521a3c86eb627004cf6b420cd7b2f6c587a0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:25 +0900 Subject: [PATCH 199/626] ASoC: pxa: spitz: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/spitz.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1671da648e95..7973466b0948 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -257,16 +257,18 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = { }; /* spitz digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(wm8750, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8750.0-001b", "wm8750-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link spitz_dai = { .name = "wm8750", .stream_name = "WM8750", - .cpu_dai_name = "pxa2xx-i2s", - .codec_dai_name = "wm8750-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm8750.0-001b", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &spitz_ops, + SND_SOC_DAILINK_REG(wm8750), }; /* spitz audio machine driver */ From 8ba9c5cbe9f27808346927bf173b263e2552f80f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:29 +0900 Subject: [PATCH 200/626] ASoC: pxa: poodle: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/poodle.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index b6693f32fc02..2a564187b2ce 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -224,16 +224,18 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { }; /* poodle digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(wm8731, + DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); + static struct snd_soc_dai_link poodle_dai = { .name = "WM8731", .stream_name = "WM8731", - .cpu_dai_name = "pxa2xx-i2s", - .codec_dai_name = "wm8731-hifi", - .platform_name = "pxa-pcm-audio", - .codec_name = "wm8731.0-001b", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &poodle_ops, + SND_SOC_DAILINK_REG(wm8731), }; /* poodle audio machine driver */ From 1d17821f79ae0fe6960231d38aaac66eed707b5f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:34 +0900 Subject: [PATCH 201/626] ASoC: kirkwood: armada-370-db: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/kirkwood/armada-370-db.c | 42 +++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c index 677a48d7b891..b2d735b610b8 100644 --- a/sound/soc/kirkwood/armada-370-db.c +++ b/sound/soc/kirkwood/armada-370-db.c @@ -58,28 +58,40 @@ static const struct snd_soc_dapm_route a370db_route[] = { { "AIN1L", NULL, "In Jack" }, }; +SND_SOC_DAILINK_DEFS(analog, + DAILINK_COMP_ARRAY(COMP_CPU("i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42l51-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(spdif_out, + DAILINK_COMP_ARRAY(COMP_CPU("spdif")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dit-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(spdif_in, + DAILINK_COMP_ARRAY(COMP_CPU("spdif")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dir-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link a370db_dai[] = { { .name = "CS42L51", .stream_name = "analog", - .cpu_dai_name = "i2s", - .codec_dai_name = "cs42l51-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, .ops = &a370db_ops, + SND_SOC_DAILINK_REG(analog), }, { .name = "S/PDIF out", .stream_name = "spdif-out", - .cpu_dai_name = "spdif", - .codec_dai_name = "dit-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(spdif_out), }, { .name = "S/PDIF in", .stream_name = "spdif-in", - .cpu_dai_name = "spdif", - .codec_dai_name = "dir-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(spdif_in), }, }; @@ -100,26 +112,26 @@ static int a370db_probe(struct platform_device *pdev) card->dev = &pdev->dev; - a370db_dai[0].cpu_of_node = + a370db_dai[0].cpus->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-controller", 0); - a370db_dai[0].platform_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[0].platforms->of_node = a370db_dai[0].cpus->of_node; - a370db_dai[0].codec_of_node = + a370db_dai[0].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-codec", 0); - a370db_dai[1].cpu_of_node = a370db_dai[0].cpu_of_node; - a370db_dai[1].platform_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[1].cpus->of_node = a370db_dai[0].cpus->of_node; + a370db_dai[1].platforms->of_node = a370db_dai[0].cpus->of_node; - a370db_dai[1].codec_of_node = + a370db_dai[1].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-codec", 1); - a370db_dai[2].cpu_of_node = a370db_dai[0].cpu_of_node; - a370db_dai[2].platform_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[2].cpus->of_node = a370db_dai[0].cpus->of_node; + a370db_dai[2].platforms->of_node = a370db_dai[0].cpus->of_node; - a370db_dai[2].codec_of_node = + a370db_dai[2].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-codec", 2); From f7554cb47ef1edf9c0000c5a96897cc9bd1f054b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:39 +0900 Subject: [PATCH 202/626] ASoC: ti: n810: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/n810.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/n810.c b/sound/soc/ti/n810.c index 9cfefe44a75f..66b69ebde97d 100644 --- a/sound/soc/ti/n810.c +++ b/sound/soc/ti/n810.c @@ -261,16 +261,19 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = { }; /* Digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(aic33, + DAILINK_COMP_ARRAY(COMP_CPU("48076000.mcbsp")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("48076000.mcbsp"))); + static struct snd_soc_dai_link n810_dai = { .name = "TLV320AIC33", .stream_name = "AIC33", - .cpu_dai_name = "48076000.mcbsp", - .platform_name = "48076000.mcbsp", - .codec_name = "tlv320aic3x-codec.1-0018", - .codec_dai_name = "tlv320aic3x-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &n810_ops, + SND_SOC_DAILINK_REG(aic33), }; /* Audio machine driver */ From 5cffc237432d47084add97e42f13dbd055c107a8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:43 +0900 Subject: [PATCH 203/626] ASoC: ti: osk5912: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/osk5912.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/osk5912.c b/sound/soc/ti/osk5912.c index e4096779ca05..0144f91f4778 100644 --- a/sound/soc/ti/osk5912.c +++ b/sound/soc/ti/osk5912.c @@ -91,16 +91,19 @@ static const struct snd_soc_dapm_route audio_map[] = { }; /* Digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(aic23, + DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic23-codec", + "tlv320aic23-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.1"))); + static struct snd_soc_dai_link osk_dai = { .name = "TLV320AIC23", .stream_name = "AIC23", - .cpu_dai_name = "omap-mcbsp.1", - .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "omap-mcbsp.1", - .codec_name = "tlv320aic23-codec", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &osk_ops, + SND_SOC_DAILINK_REG(aic23), }; /* Audio machine driver */ From acb9a2d52e2c4839c7fcfb72c06ab437eed9cc92 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:48 +0900 Subject: [PATCH 204/626] ASoC: ti: ams-delta: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/ams-delta.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index b9611db14c86..50ca3c42642f 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -518,17 +518,19 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) } /* DAI glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(cx20442, + DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("cx20442-codec", "cx20442-voice")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.1"))); + static struct snd_soc_dai_link ams_delta_dai_link = { .name = "CX20442", .stream_name = "CX20442", - .cpu_dai_name = "omap-mcbsp.1", - .codec_dai_name = "cx20442-voice", .init = ams_delta_cx20442_init, - .platform_name = "omap-mcbsp.1", - .codec_name = "cx20442-codec", .ops = &ams_delta_ops, .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(cx20442), }; /* Audio card driver */ From 77723f1c262f39b4d82eb5fda7ac045c0aea8e3d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:52 +0900 Subject: [PATCH 205/626] ASoC: ti: omap3pandora: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap3pandora.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/soc/ti/omap3pandora.c b/sound/soc/ti/omap3pandora.c index 4e3de712159c..3d52b6b008ce 100644 --- a/sound/soc/ti/omap3pandora.c +++ b/sound/soc/ti/omap3pandora.c @@ -189,29 +189,33 @@ static const struct snd_soc_ops omap3pandora_ops = { }; /* Digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(out, + DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.2")), + DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.2"))); + +SND_SOC_DAILINK_DEFS(in, + DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.4")), + DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.4"))); + static struct snd_soc_dai_link omap3pandora_dai[] = { { .name = "PCM1773", .stream_name = "HiFi Out", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-mcbsp.2", - .codec_name = "twl4030-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &omap3pandora_ops, .init = omap3pandora_out_init, + SND_SOC_DAILINK_REG(out), }, { .name = "TWL4030", .stream_name = "Line/Mic In", - .cpu_dai_name = "omap-mcbsp.4", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-mcbsp.4", - .codec_name = "twl4030-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &omap3pandora_ops, .init = omap3pandora_in_init, + SND_SOC_DAILINK_REG(in), } }; From de3582fec0aacdca484d68ca693e255f2617d8ec Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:12:57 +0900 Subject: [PATCH 206/626] ASoC: ti: davinci-evm: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/davinci-evm.c | 105 +++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 38 deletions(-) diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c index 4869d6311510..bd822bc8040f 100644 --- a/sound/soc/ti/davinci-evm.c +++ b/sound/soc/ti/davinci-evm.c @@ -143,103 +143,127 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) } /* davinci-evm digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(dm6446, + DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-001b", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp"))); + static struct snd_soc_dai_link dm6446_evm_dai = { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-mcbsp", .init = evm_aic3x_init, .ops = &evm_ops, .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, + SND_SOC_DAILINK_REG(dm6446), }; +SND_SOC_DAILINK_DEFS(dm355, + DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-001b", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp.1"))); + static struct snd_soc_dai_link dm355_evm_dai = { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp.1", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-mcbsp.1", .init = evm_aic3x_init, .ops = &evm_ops, .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, + SND_SOC_DAILINK_REG(dm355), }; +#ifdef CONFIG_SND_SOC_DM365_AIC3X_CODEC +SND_SOC_DAILINK_DEFS(dm365, + DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp"))); +#elif defined(CONFIG_SND_SOC_DM365_VOICE_CODEC) +SND_SOC_DAILINK_DEFS(dm365, + DAILINK_COMP_ARRAY(COMP_CPU("davinci-vcif")), + DAILINK_COMP_ARRAY(COMP_CODEC("cq93vc-codec", "cq93vc-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-vcif"))); +#endif + static struct snd_soc_dai_link dm365_evm_dai = { #ifdef CONFIG_SND_SOC_DM365_AIC3X_CODEC .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-mcbsp", .init = evm_aic3x_init, .ops = &evm_ops, .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, + SND_SOC_DAILINK_REG(dm365), #elif defined(CONFIG_SND_SOC_DM365_VOICE_CODEC) .name = "Voice Codec - CQ93VC", .stream_name = "CQ93", - .cpu_dai_name = "davinci-vcif", - .codec_dai_name = "cq93vc-hifi", - .codec_name = "cq93vc-codec", - .platform_name = "davinci-vcif", + SND_SOC_DAILINK_REG(dm365), #endif }; +SND_SOC_DAILINK_DEFS(dm6467_aic3x, + DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.0-001a", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.0"))); + +SND_SOC_DAILINK_DEFS(dm6467_spdif, + DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("spdif_dit", "dit-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.1"))); + static struct snd_soc_dai_link dm6467_evm_dai[] = { { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai_name= "davinci-mcasp.0", - .codec_dai_name = "tlv320aic3x-hifi", - .platform_name = "davinci-mcasp.0", - .codec_name = "tlv320aic3x-codec.0-001a", .init = evm_aic3x_init, .ops = &evm_ops, .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, + SND_SOC_DAILINK_REG(dm6467_aic3x), }, { .name = "McASP", .stream_name = "spdif", - .cpu_dai_name= "davinci-mcasp.1", - .codec_dai_name = "dit-hifi", - .codec_name = "spdif_dit", - .platform_name = "davinci-mcasp.1", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, + SND_SOC_DAILINK_REG(dm6467_spdif), }, }; +SND_SOC_DAILINK_DEFS(da830, + DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.1"))); + static struct snd_soc_dai_link da830_evm_dai = { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcasp.1", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-mcasp.1", .init = evm_aic3x_init, .ops = &evm_ops, .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, + SND_SOC_DAILINK_REG(da830), }; +SND_SOC_DAILINK_DEFS(da850, + DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.0"))); + static struct snd_soc_dai_link da850_evm_dai = { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai_name= "davinci-mcasp.0", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-mcasp.0", .init = evm_aic3x_init, .ops = &evm_ops, .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, + SND_SOC_DAILINK_REG(da850), }; /* davinci dm6446 evm audio machine driver */ @@ -330,14 +354,19 @@ static struct snd_soc_card da850_snd_soc_card = { * The struct is used as place holder. It will be completely * filled with data from dt node. */ +SND_SOC_DAILINK_DEFS(evm, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link evm_dai_tlv320aic3x = { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .codec_dai_name = "tlv320aic3x-hifi", .ops = &evm_ops, .init = evm_aic3x_init, .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, + SND_SOC_DAILINK_REG(evm), }; static const struct of_device_id davinci_evm_dt_ids[] = { @@ -374,15 +403,15 @@ static int davinci_evm_probe(struct platform_device *pdev) evm_soc_card.dai_link = dai; - dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0); - if (!dai->codec_of_node) + dai->codecs->of_node = of_parse_phandle(np, "ti,audio-codec", 0); + if (!dai->codecs->of_node) return -EINVAL; - dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0); - if (!dai->cpu_of_node) + dai->cpus->of_node = of_parse_phandle(np, "ti,mcasp-controller", 0); + if (!dai->cpus->of_node) return -EINVAL; - dai->platform_of_node = dai->cpu_of_node; + dai->platforms->of_node = dai->cpus->of_node; evm_soc_card.dev = &pdev->dev; ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model"); From 3b785a63ee3d2bc9eb6473ca9490d5a268c88c3e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:02 +0900 Subject: [PATCH 207/626] ASoC: ti: omap-hdmi: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-hdmi.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index 673a9eb153b2..11c1440da226 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -321,6 +321,7 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) struct hdmi_audio_data *ad; struct snd_soc_dai_driver *dai_drv; struct snd_soc_card *card; + struct snd_soc_dai_link_component *compnent; int ret; if (!ha) { @@ -371,12 +372,23 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL); if (!card->dai_link) return -ENOMEM; + + compnent = devm_kzalloc(dev, 3 * sizeof(*compnent), GFP_KERNEL); + if (!compnent) + return -ENOMEM; + card->dai_link->cpus = &compnent[0]; + card->dai_link->num_cpus = 1; + card->dai_link->codecs = &compnent[1]; + card->dai_link->num_codecs = 1; + card->dai_link->platforms = &compnent[2]; + card->dai_link->num_platforms = 1; + card->dai_link->name = card->name; card->dai_link->stream_name = card->name; - card->dai_link->cpu_dai_name = dev_name(ad->dssdev); - card->dai_link->platform_name = dev_name(ad->dssdev); - card->dai_link->codec_name = "snd-soc-dummy"; - card->dai_link->codec_dai_name = "snd-soc-dummy-dai"; + card->dai_link->cpus->dai_name = dev_name(ad->dssdev); + card->dai_link->platforms->name = dev_name(ad->dssdev); + card->dai_link->codecs->name = "snd-soc-dummy"; + card->dai_link->codecs->dai_name = "snd-soc-dummy-dai"; card->num_links = 1; card->dev = dev; From bc9dfc4cb1d817726774c1ab57c8f866a5e109db Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:06 +0900 Subject: [PATCH 208/626] ASoC: ti: omap-abe-twl6040: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-abe-twl6040.c | 36 +++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c index fed45b41f9d3..3522ea7aa8d9 100644 --- a/sound/soc/ti/omap-abe-twl6040.c +++ b/sound/soc/ti/omap-abe-twl6040.c @@ -35,6 +35,18 @@ #include "omap-mcpdm.h" #include "../codecs/twl6040.h" +SND_SOC_DAILINK_DEFS(link0, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC("twl6040-codec", + "twl6040-legacy")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(link1, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", + "dmic-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + struct abe_twl6040 { struct snd_soc_card card; struct snd_soc_dai_link dai_links[2]; @@ -255,10 +267,14 @@ static int omap_abe_probe(struct platform_device *pdev) priv->dai_links[0].name = "DMIC"; priv->dai_links[0].stream_name = "TWL6040"; - priv->dai_links[0].cpu_of_node = dai_node; - priv->dai_links[0].platform_of_node = dai_node; - priv->dai_links[0].codec_dai_name = "twl6040-legacy"; - priv->dai_links[0].codec_name = "twl6040-codec"; + priv->dai_links[0].cpus = link0_cpus; + priv->dai_links[0].num_cpus = 1; + priv->dai_links[0].cpus->of_node = dai_node; + priv->dai_links[0].platforms = link0_platforms; + priv->dai_links[0].num_platforms = 1; + priv->dai_links[0].platforms->of_node = dai_node; + priv->dai_links[0].codecs = link0_codecs; + priv->dai_links[0].num_codecs = 1; priv->dai_links[0].init = omap_abe_twl6040_init; priv->dai_links[0].ops = &omap_abe_ops; @@ -267,10 +283,14 @@ static int omap_abe_probe(struct platform_device *pdev) num_links = 2; priv->dai_links[1].name = "TWL6040"; priv->dai_links[1].stream_name = "DMIC Capture"; - priv->dai_links[1].cpu_of_node = dai_node; - priv->dai_links[1].platform_of_node = dai_node; - priv->dai_links[1].codec_dai_name = "dmic-hifi"; - priv->dai_links[1].codec_name = "dmic-codec"; + priv->dai_links[1].cpus = link1_cpus; + priv->dai_links[1].num_cpus = 1; + priv->dai_links[1].cpus->of_node = dai_node; + priv->dai_links[1].platforms = link1_platforms; + priv->dai_links[1].num_platforms = 1; + priv->dai_links[1].platforms->of_node = dai_node; + priv->dai_links[1].codecs = link1_codecs; + priv->dai_links[1].num_codecs = 1; priv->dai_links[1].init = omap_abe_dmic_init; priv->dai_links[1].ops = &omap_abe_dmic_ops; } else { From d6db366a411c7e3ecc13096c58a290593be7a804 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:11 +0900 Subject: [PATCH 209/626] ASoC: ti: omap-twl4030: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-twl4030.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/sound/soc/ti/omap-twl4030.c b/sound/soc/ti/omap-twl4030.c index cccc316743fa..ddd24b2809b8 100644 --- a/sound/soc/ti/omap-twl4030.c +++ b/sound/soc/ti/omap-twl4030.c @@ -209,26 +209,30 @@ static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) } /* Digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.2")), + DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.2"))); + +SND_SOC_DAILINK_DEFS(voice, + DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.3")), + DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-voice")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.3"))); + static struct snd_soc_dai_link omap_twl4030_dai_links[] = { { .name = "TWL4030 HiFi", .stream_name = "TWL4030 HiFi", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-mcbsp.2", - .codec_name = "twl4030-codec", .init = omap_twl4030_init, .ops = &omap_twl4030_ops, + SND_SOC_DAILINK_REG(hifi), }, { .name = "TWL4030 Voice", .stream_name = "TWL4030 Voice", - .cpu_dai_name = "omap-mcbsp.3", - .codec_dai_name = "twl4030-voice", - .platform_name = "omap-mcbsp.3", - .codec_name = "twl4030-codec", .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(voice), }, }; @@ -272,21 +276,21 @@ static int omap_twl4030_probe(struct platform_device *pdev) dev_err(&pdev->dev, "McBSP node is not provided\n"); return -EINVAL; } - omap_twl4030_dai_links[0].cpu_dai_name = NULL; - omap_twl4030_dai_links[0].cpu_of_node = dai_node; + omap_twl4030_dai_links[0].cpus->dai_name = NULL; + omap_twl4030_dai_links[0].cpus->of_node = dai_node; - omap_twl4030_dai_links[0].platform_name = NULL; - omap_twl4030_dai_links[0].platform_of_node = dai_node; + omap_twl4030_dai_links[0].platforms->name = NULL; + omap_twl4030_dai_links[0].platforms->of_node = dai_node; dai_node = of_parse_phandle(node, "ti,mcbsp-voice", 0); if (!dai_node) { card->num_links = 1; } else { - omap_twl4030_dai_links[1].cpu_dai_name = NULL; - omap_twl4030_dai_links[1].cpu_of_node = dai_node; + omap_twl4030_dai_links[1].cpus->dai_name = NULL; + omap_twl4030_dai_links[1].cpus->of_node = dai_node; - omap_twl4030_dai_links[1].platform_name = NULL; - omap_twl4030_dai_links[1].platform_of_node = dai_node; + omap_twl4030_dai_links[1].platforms->name = NULL; + omap_twl4030_dai_links[1].platforms->of_node = dai_node; } priv->jack_detect = of_get_named_gpio(node, From c3e2a4af64cb74ea66abca1c80aa38b0c9d15567 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:15 +0900 Subject: [PATCH 210/626] ASoC: ti: rx51: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/rx51.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index 57448bd5ad77..0684f961de76 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -312,18 +312,21 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) } /* Digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(aic34, + DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.2")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.2-0018", + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.2"))); + static struct snd_soc_dai_link rx51_dai[] = { { .name = "TLV320AIC34", .stream_name = "AIC34", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "tlv320aic3x-hifi", - .platform_name = "omap-mcbsp.2", - .codec_name = "tlv320aic3x-codec.2-0018", .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM, .init = rx51_aic34_init, .ops = &rx51_ops, + SND_SOC_DAILINK_REG(aic34), }, }; @@ -389,18 +392,18 @@ static int rx51_soc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "McBSP node is not provided\n"); return -EINVAL; } - rx51_dai[0].cpu_dai_name = NULL; - rx51_dai[0].platform_name = NULL; - rx51_dai[0].cpu_of_node = dai_node; - rx51_dai[0].platform_of_node = dai_node; + rx51_dai[0].cpus->dai_name = NULL; + rx51_dai[0].platforms->name = NULL; + rx51_dai[0].cpus->of_node = dai_node; + rx51_dai[0].platforms->of_node = dai_node; dai_node = of_parse_phandle(np, "nokia,audio-codec", 0); if (!dai_node) { dev_err(&pdev->dev, "Codec node is not provided\n"); return -EINVAL; } - rx51_dai[0].codec_name = NULL; - rx51_dai[0].codec_of_node = dai_node; + rx51_dai[0].codecs->name = NULL; + rx51_dai[0].codecs->of_node = dai_node; dai_node = of_parse_phandle(np, "nokia,audio-codec", 1); if (!dai_node) { From 4f209c5142dcdd4db29f734d652fba4d2ab6da71 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:20 +0900 Subject: [PATCH 211/626] ASoC: sh: migor: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/migor.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index 8739c9f60672..991557e25eba 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -123,16 +123,18 @@ static const struct snd_soc_dapm_route audio_map[] = { }; /* migor digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(wm8978, + DAILINK_COMP_ARRAY(COMP_CPU("siu-pcm-audio")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8978.0-001a", "wm8978-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("siu-pcm-audio"))); + static struct snd_soc_dai_link migor_dai = { .name = "wm8978", .stream_name = "WM8978", - .cpu_dai_name = "siu-pcm-audio", - .codec_dai_name = "wm8978-hifi", - .platform_name = "siu-pcm-audio", - .codec_name = "wm8978.0-001a", .dai_fmt = SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, .ops = &migor_dai_ops, + SND_SOC_DAILINK_REG(wm8978), }; /* migor audio machine driver */ From f9aaa1929b2e828d87aee9adb003cd19fbf18f57 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:24 +0900 Subject: [PATCH 212/626] ASoC: sh: sh7760-ac97: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/sh7760-ac97.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c index 4bb4c13cf860..d267243a159b 100644 --- a/sound/soc/sh/sh7760-ac97.c +++ b/sound/soc/sh/sh7760-ac97.c @@ -14,14 +14,15 @@ #define IPSEL 0xFE400034 +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("hac-dai.0")), /* HAC0 */ + DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("sh7760-pcm-audio"))); + static struct snd_soc_dai_link sh7760_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "hac-dai.0", /* HAC0 */ - .codec_dai_name = "ac97-hifi", - .platform_name = "sh7760-pcm-audio", - .codec_name = "ac97-codec", - .ops = NULL, + SND_SOC_DAILINK_REG(ac97), }; static struct snd_soc_card sh7760_ac97_soc_machine = { From 48696d0a6d8e5bd2c9e03b70e93f9cf0db31705f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:29 +0900 Subject: [PATCH 213/626] ASoC: amd: acp-da7219-max98357a: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/amd/acp-da7219-max98357a.c | 42 +++++++++++++++------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 16b0ea3a3d72..f4ee6798154a 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -298,69 +298,71 @@ static const struct snd_soc_ops cz_dmic1_cap_ops = { .hw_params = cz_da7219_params, }; +SND_SOC_DAILINK_DEF(designware1, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1.auto"))); +SND_SOC_DAILINK_DEF(designware2, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2.auto"))); +SND_SOC_DAILINK_DEF(designware3, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.3.auto"))); + +SND_SOC_DAILINK_DEF(dlgs, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", "da7219-hifi"))); +SND_SOC_DAILINK_DEF(mx, + DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); +SND_SOC_DAILINK_DEF(adau, + DAILINK_COMP_ARRAY(COMP_CODEC("ADAU7002:00", "adau7002-hifi"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0.auto"))); + static struct snd_soc_dai_link cz_dai_7219_98357[] = { { .name = "amd-da7219-play", .stream_name = "Playback", - .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.1.auto", - .codec_dai_name = "da7219-hifi", - .codec_name = "i2c-DLGS7219:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .init = cz_da7219_init, .dpcm_playback = 1, .ops = &cz_da7219_play_ops, + SND_SOC_DAILINK_REG(designware1, dlgs, platform), }, { .name = "amd-da7219-cap", .stream_name = "Capture", - .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.2.auto", - .codec_dai_name = "da7219-hifi", - .codec_name = "i2c-DLGS7219:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .dpcm_capture = 1, .ops = &cz_da7219_cap_ops, + SND_SOC_DAILINK_REG(designware2, dlgs, platform), }, { .name = "amd-max98357-play", .stream_name = "HiFi Playback", - .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.3.auto", - .codec_dai_name = "HiFi", - .codec_name = "MX98357A:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .dpcm_playback = 1, .ops = &cz_max_play_ops, + SND_SOC_DAILINK_REG(designware3, mx, platform), }, { /* C panel DMIC */ .name = "dmic0", .stream_name = "DMIC0 Capture", - .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.3.auto", - .codec_dai_name = "adau7002-hifi", - .codec_name = "ADAU7002:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .dpcm_capture = 1, .ops = &cz_dmic0_cap_ops, + SND_SOC_DAILINK_REG(designware3, adau, platform), }, { /* A/B panel DMIC */ .name = "dmic1", .stream_name = "DMIC1 Capture", - .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.2.auto", - .codec_dai_name = "adau7002-hifi", - .codec_name = "ADAU7002:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .dpcm_capture = 1, .ops = &cz_dmic1_cap_ops, + SND_SOC_DAILINK_REG(designware2, adau, platform), }, }; From 19913c163e219376e543e8138ca4f05670ee9f4a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:33 +0900 Subject: [PATCH 214/626] ASoC: amd: acp-rt5645: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/amd/acp-rt5645.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sound/soc/amd/acp-rt5645.c b/sound/soc/amd/acp-rt5645.c index b79b922b08a0..91abeb92b648 100644 --- a/sound/soc/amd/acp-rt5645.c +++ b/sound/soc/amd/acp-rt5645.c @@ -95,29 +95,34 @@ static struct snd_soc_ops cz_aif1_ops = { .hw_params = cz_aif1_hw_params, }; +SND_SOC_DAILINK_DEF(designware1, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1.auto"))); +SND_SOC_DAILINK_DEF(designware2, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2.auto"))); + +SND_SOC_DAILINK_DEF(codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5650:00", "rt5645-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0.auto"))); + static struct snd_soc_dai_link cz_dai_rt5650[] = { { .name = "amd-rt5645-play", .stream_name = "RT5645_AIF1", - .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.1.auto", - .codec_dai_name = "rt5645-aif1", - .codec_name = "i2c-10EC5650:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .init = cz_init, .ops = &cz_aif1_ops, + SND_SOC_DAILINK_REG(designware1, codec, platform), }, { .name = "amd-rt5645-cap", .stream_name = "RT5645_AIF1", - .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.2.auto", - .codec_dai_name = "rt5645-aif1", - .codec_name = "i2c-10EC5650:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &cz_aif1_ops, + SND_SOC_DAILINK_REG(designware2, codec, platform), }, }; From ed00d6ccde62a7deafdfbf22d37725945890e536 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:38 +0900 Subject: [PATCH 215/626] ASoC: atmel: mikroe-proto: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Tested-by: Codrin Ciubotariu Signed-off-by: Mark Brown --- sound/soc/atmel/mikroe-proto.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/mikroe-proto.c b/sound/soc/atmel/mikroe-proto.c index d47aaa5bf75a..255168a9df5b 100644 --- a/sound/soc/atmel/mikroe-proto.c +++ b/sound/soc/atmel/mikroe-proto.c @@ -66,6 +66,7 @@ static struct snd_soc_card snd_proto = { static int snd_proto_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai; + struct snd_soc_dai_link_component *comp; struct device_node *np = pdev->dev.of_node; struct device_node *codec_np, *cpu_np; struct device_node *bitclkmaster = NULL; @@ -87,12 +88,24 @@ static int snd_proto_probe(struct platform_device *pdev) if (!dai) return -ENOMEM; + /* for cpus/codecs/platforms */ + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!comp) + return -ENOMEM; + snd_proto.dai_link = dai; snd_proto.num_links = 1; + dai->cpus = &comp[0]; + dai->num_cpus = 1; + dai->codecs = &comp[1]; + dai->num_codecs = 1; + dai->platforms = &comp[2]; + dai->num_platforms = 1; + dai->name = "WM8731"; dai->stream_name = "WM8731 HiFi"; - dai->codec_dai_name = "wm8731-hifi"; + dai->codecs->dai_name = "wm8731-hifi"; dai->init = &snd_proto_init; codec_np = of_parse_phandle(np, "audio-codec", 0); @@ -100,15 +113,15 @@ static int snd_proto_probe(struct platform_device *pdev) dev_err(&pdev->dev, "audio-codec node missing\n"); return -EINVAL; } - dai->codec_of_node = codec_np; + dai->codecs->of_node = codec_np; cpu_np = of_parse_phandle(np, "i2s-controller", 0); if (!cpu_np) { dev_err(&pdev->dev, "i2s-controller missing\n"); return -EINVAL; } - dai->cpu_of_node = cpu_np; - dai->platform_of_node = cpu_np; + dai->cpus->of_node = cpu_np; + dai->platforms->of_node = cpu_np; dai_fmt = snd_soc_of_parse_daifmt(np, NULL, &bitclkmaster, &framemaster); From 35617d8262c49a1d63a36ef291c5b1a8fdc86bc8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:42 +0900 Subject: [PATCH 216/626] ASoC: atmel: sam9x5_wm8731: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/sam9x5_wm8731.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index e6c303ab869d..36917acc161f 100644 --- a/sound/soc/atmel/sam9x5_wm8731.c +++ b/sound/soc/atmel/sam9x5_wm8731.c @@ -82,6 +82,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) struct snd_soc_card *card; struct snd_soc_dai_link *dai; struct sam9x5_drvdata *priv; + struct snd_soc_dai_link_component *comp; int ret; if (!np) { @@ -92,7 +93,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL); - if (!dai || !card || !priv) { + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!dai || !card || !priv || !comp) { ret = -ENOMEM; goto out; } @@ -105,9 +107,17 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) card->num_links = 1; card->dapm_widgets = sam9x5_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(sam9x5_dapm_widgets); + + dai->cpus = &comp[0]; + dai->num_cpus = 1; + dai->codecs = &comp[1]; + dai->num_codecs = 1; + dai->platforms = &comp[2]; + dai->num_platforms = 1; + dai->name = "WM8731"; dai->stream_name = "WM8731 PCM"; - dai->codec_dai_name = "wm8731-hifi"; + dai->codecs->dai_name = "wm8731-hifi"; dai->init = sam9x5_wm8731_init; dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; @@ -131,7 +141,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) goto out; } - dai->codec_of_node = codec_np; + dai->codecs->of_node = codec_np; cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); if (!cpu_np) { @@ -139,8 +149,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) ret = -EINVAL; goto out; } - dai->cpu_of_node = cpu_np; - dai->platform_of_node = cpu_np; + dai->cpus->of_node = cpu_np; + dai->platforms->of_node = cpu_np; priv->ssc_id = of_alias_get_id(cpu_np, "ssc"); From d83923c576f985e8442734d4d89f72af7661fec2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:46 +0900 Subject: [PATCH 217/626] ASoC: atmel: sam9g20_wm8731: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/sam9g20_wm8731.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 98f93e79c654..a5b4c3905ae8 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -129,16 +129,18 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(pcm, + DAILINK_COMP_ARRAY(COMP_CPU("at91rm9200_ssc.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("at91rm9200_ssc.0"))); + static struct snd_soc_dai_link at91sam9g20ek_dai = { .name = "WM8731", .stream_name = "WM8731 PCM", - .cpu_dai_name = "at91rm9200_ssc.0", - .codec_dai_name = "wm8731-hifi", .init = at91sam9g20ek_wm8731_init, - .platform_name = "at91rm9200_ssc.0", - .codec_name = "wm8731.0-001b", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(pcm), }; static struct snd_soc_card snd_soc_at91sam9g20ek = { @@ -211,24 +213,24 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev) goto err; /* Parse codec info */ - at91sam9g20ek_dai.codec_name = NULL; + at91sam9g20ek_dai.codecs->name = NULL; codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); if (!codec_np) { dev_err(&pdev->dev, "codec info missing\n"); return -EINVAL; } - at91sam9g20ek_dai.codec_of_node = codec_np; + at91sam9g20ek_dai.codecs->of_node = codec_np; /* Parse dai and platform info */ - at91sam9g20ek_dai.cpu_dai_name = NULL; - at91sam9g20ek_dai.platform_name = NULL; + at91sam9g20ek_dai.cpus->dai_name = NULL; + at91sam9g20ek_dai.platforms->name = NULL; cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); if (!cpu_np) { dev_err(&pdev->dev, "dai and pcm info missing\n"); return -EINVAL; } - at91sam9g20ek_dai.cpu_of_node = cpu_np; - at91sam9g20ek_dai.platform_of_node = cpu_np; + at91sam9g20ek_dai.cpus->of_node = cpu_np; + at91sam9g20ek_dai.platforms->of_node = cpu_np; of_node_put(codec_np); of_node_put(cpu_np); From 1199dd99ddf699dd81c764016b8b6a9fd599d0d4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:51 +0900 Subject: [PATCH 218/626] ASoC: atmel: tse850-pcm5142: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/tse850-pcm5142.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index ae445184614a..59e2edb22b3a 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -294,13 +294,18 @@ static const struct snd_soc_dapm_route tse850_intercon[] = { { "DAC", NULL, "OUTL" }, }; +SND_SOC_DAILINK_DEFS(pcm, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tse850_dailink = { .name = "TSE-850", .stream_name = "TSE-850-PCM", - .codec_dai_name = "pcm512x-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFS, + SND_SOC_DAILINK_REG(pcm), }; static struct snd_soc_card tse850_card = { @@ -331,8 +336,8 @@ static int tse850_dt_init(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get cpu dai\n"); return -EINVAL; } - dailink->cpu_of_node = cpu_np; - dailink->platform_of_node = cpu_np; + dailink->cpus->of_node = cpu_np; + dailink->platforms->of_node = cpu_np; of_node_put(cpu_np); codec_np = of_parse_phandle(np, "axentia,audio-codec", 0); @@ -340,7 +345,7 @@ static int tse850_dt_init(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get codec info\n"); return -EINVAL; } - dailink->codec_of_node = codec_np; + dailink->codecs->of_node = codec_np; of_node_put(codec_np); return 0; From 079878be6fea4e5671e9fb9020985e4f2b45289c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:13:55 +0900 Subject: [PATCH 219/626] ASoC: atmel: atmel-wm8904: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_wm8904.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index fbc10f61eb55..084788ed328c 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c @@ -57,14 +57,19 @@ static const struct snd_soc_ops atmel_asoc_wm8904_ops = { .hw_params = atmel_asoc_wm8904_hw_params, }; +SND_SOC_DAILINK_DEFS(pcm, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8904-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { .name = "WM8904", .stream_name = "WM8904 PCM", - .codec_dai_name = "wm8904-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &atmel_asoc_wm8904_ops, + SND_SOC_DAILINK_REG(pcm), }; static struct snd_soc_card atmel_asoc_wm8904_card = { @@ -108,8 +113,8 @@ static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev) ret = -EINVAL; return ret; } - dailink->cpu_of_node = cpu_np; - dailink->platform_of_node = cpu_np; + dailink->cpus->of_node = cpu_np; + dailink->platforms->of_node = cpu_np; of_node_put(cpu_np); codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); @@ -118,7 +123,7 @@ static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev) ret = -EINVAL; return ret; } - dailink->codec_of_node = codec_np; + dailink->codecs->of_node = codec_np; of_node_put(codec_np); return 0; @@ -137,7 +142,7 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev) return ret; } - id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc"); + id = of_alias_get_id((struct device_node *)dailink->cpus->of_node, "ssc"); ret = atmel_ssc_set_audio(id); if (ret != 0) { dev_err(&pdev->dev, "failed to set SSC %d for audio\n", id); @@ -163,7 +168,7 @@ static int atmel_asoc_wm8904_remove(struct platform_device *pdev) struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; int id; - id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc"); + id = of_alias_get_id((struct device_node *)dailink->cpus->of_node, "ssc"); snd_soc_unregister_card(card); atmel_ssc_put_audio(id); From f62da10aba7cc7971dace102ad5cc129e4dfbd94 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:00 +0900 Subject: [PATCH 220/626] ASoC: atmel: atmel-pdmic: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-pdmic.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 915c2b064de1..f53213402d94 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -511,17 +511,30 @@ static int atmel_pdmic_asoc_card_init(struct device *dev, { struct snd_soc_dai_link *dai_link; struct atmel_pdmic *dd = snd_soc_card_get_drvdata(card); + struct snd_soc_dai_link_component *comp; dai_link = devm_kzalloc(dev, sizeof(*dai_link), GFP_KERNEL); if (!dai_link) return -ENOMEM; + comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!comp) + return -ENOMEM; + + dai_link->cpus = &comp[0]; + dai_link->codecs = &comp[1]; + dai_link->platforms = &comp[2]; + + dai_link->num_cpus = 1; + dai_link->num_codecs = 1; + dai_link->num_platforms = 1; + dai_link->name = "PDMIC"; dai_link->stream_name = "PDMIC PCM"; - dai_link->codec_dai_name = ATMEL_PDMIC_CODEC_DAI_NAME; - dai_link->cpu_dai_name = dev_name(dev); - dai_link->codec_name = dev_name(dev); - dai_link->platform_name = dev_name(dev); + dai_link->codecs->dai_name = ATMEL_PDMIC_CODEC_DAI_NAME; + dai_link->cpus->dai_name = dev_name(dev); + dai_link->codecs->name = dev_name(dev); + dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From 3d14a1df7d301eb12592297c4b4ec0a00d76b0f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:04 +0900 Subject: [PATCH 221/626] ASoC: atmel: atmel-classd: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 3d70061901a0..cfebbeb92ef1 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -500,17 +500,30 @@ static int atmel_classd_asoc_card_init(struct device *dev, { struct snd_soc_dai_link *dai_link; struct atmel_classd *dd = snd_soc_card_get_drvdata(card); + struct snd_soc_dai_link_component *comp; dai_link = devm_kzalloc(dev, sizeof(*dai_link), GFP_KERNEL); if (!dai_link) return -ENOMEM; + comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!comp) + return -ENOMEM; + + dai_link->cpus = &comp[0]; + dai_link->codecs = &comp[1]; + dai_link->platforms = &comp[2]; + + dai_link->num_cpus = 1; + dai_link->num_codecs = 1; + dai_link->num_platforms = 1; + dai_link->name = "CLASSD"; dai_link->stream_name = "CLASSD PCM"; - dai_link->codec_dai_name = ATMEL_CLASSD_CODEC_DAI_NAME; - dai_link->cpu_dai_name = dev_name(dev); - dai_link->codec_name = dev_name(dev); - dai_link->platform_name = dev_name(dev); + dai_link->codecs->dai_name = ATMEL_CLASSD_CODEC_DAI_NAME; + dai_link->cpus->dai_name = dev_name(dev); + dai_link->codecs->name = dev_name(dev); + dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From 34592f7ecb4e0b1c79ab5669ed3fcbee0ae4b835 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:09 +0900 Subject: [PATCH 222/626] ASoC: au1x: db1000: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/au1x/db1000.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/au1x/db1000.c b/sound/soc/au1x/db1000.c index e97c32798e98..5819b897bdd8 100644 --- a/sound/soc/au1x/db1000.c +++ b/sound/soc/au1x/db1000.c @@ -18,13 +18,15 @@ #include "psc.h" +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("alchemy-ac97c")), + DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("alchemy-pcm-dma.0"))); + static struct snd_soc_dai_link db1000_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .codec_dai_name = "ac97-hifi", - .cpu_dai_name = "alchemy-ac97c", - .platform_name = "alchemy-pcm-dma.0", - .codec_name = "ac97-codec", + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card db1000_ac97 = { From fc4b060a8c6357b2ee22fe21f261f2fb77d41706 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:13 +0900 Subject: [PATCH 223/626] ASoC: au1x: db1200: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/au1x/db1200.c | 50 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index 301e1fc9a377..4b012bf54c37 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -46,13 +46,15 @@ static const struct platform_device_id db1200_pids[] = { /*------------------------- AC97 PART ---------------------------*/ +SND_SOC_DAILINK_DEFS(db1200_ac97, + DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_ac97.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec.1", "ac97-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.1"))); + static struct snd_soc_dai_link db1200_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .codec_dai_name = "ac97-hifi", - .cpu_dai_name = "au1xpsc_ac97.1", - .platform_name = "au1xpsc-pcm.1", - .codec_name = "ac97-codec.1", + SND_SOC_DAILINK_REG(db1200_ac97), }; static struct snd_soc_card db1200_ac97_machine = { @@ -62,13 +64,15 @@ static struct snd_soc_card db1200_ac97_machine = { .num_links = 1, }; +SND_SOC_DAILINK_DEFS(db1300_ac97, + DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_ac97.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec.1", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.1"))); + static struct snd_soc_dai_link db1300_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .codec_dai_name = "wm9712-hifi", - .cpu_dai_name = "au1xpsc_ac97.1", - .platform_name = "au1xpsc-pcm.1", - .codec_name = "wm9712-codec.1", + SND_SOC_DAILINK_REG(db1300_ac97), }; static struct snd_soc_card db1300_ac97_machine = { @@ -103,16 +107,18 @@ static const struct snd_soc_ops db1200_i2s_wm8731_ops = { .startup = db1200_i2s_startup, }; +SND_SOC_DAILINK_DEFS(db1200_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_i2s.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.1"))); + static struct snd_soc_dai_link db1200_i2s_dai = { .name = "WM8731", .stream_name = "WM8731 PCM", - .codec_dai_name = "wm8731-hifi", - .cpu_dai_name = "au1xpsc_i2s.1", - .platform_name = "au1xpsc-pcm.1", - .codec_name = "wm8731.0-001b", .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &db1200_i2s_wm8731_ops, + SND_SOC_DAILINK_REG(db1200_i2s), }; static struct snd_soc_card db1200_i2s_machine = { @@ -122,16 +128,18 @@ static struct snd_soc_card db1200_i2s_machine = { .num_links = 1, }; +SND_SOC_DAILINK_DEFS(db1300_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_i2s.2")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.2"))); + static struct snd_soc_dai_link db1300_i2s_dai = { .name = "WM8731", .stream_name = "WM8731 PCM", - .codec_dai_name = "wm8731-hifi", - .cpu_dai_name = "au1xpsc_i2s.2", - .platform_name = "au1xpsc-pcm.2", - .codec_name = "wm8731.0-001b", .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &db1200_i2s_wm8731_ops, + SND_SOC_DAILINK_REG(db1300_i2s), }; static struct snd_soc_card db1300_i2s_machine = { @@ -141,16 +149,18 @@ static struct snd_soc_card db1300_i2s_machine = { .num_links = 1, }; +SND_SOC_DAILINK_DEFS(db1550_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_i2s.3")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.3"))); + static struct snd_soc_dai_link db1550_i2s_dai = { .name = "WM8731", .stream_name = "WM8731 PCM", - .codec_dai_name = "wm8731-hifi", - .cpu_dai_name = "au1xpsc_i2s.3", - .platform_name = "au1xpsc-pcm.3", - .codec_name = "wm8731.0-001b", .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &db1200_i2s_wm8731_ops, + SND_SOC_DAILINK_REG(db1550_i2s), }; static struct snd_soc_card db1550_i2s_machine = { From 5e883ff15fc079a8004a104209e2ecb14e5b4bb0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:18 +0900 Subject: [PATCH 224/626] ASoC: cirrus: edb93xx: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/cirrus/edb93xx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index f678b4c1514a..1528d1410ff2 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c @@ -60,16 +60,18 @@ static const struct snd_soc_ops edb93xx_ops = { .hw_params = edb93xx_hw_params, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("ep93xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "cs4271-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("ep93xx-i2s"))); + static struct snd_soc_dai_link edb93xx_dai = { .name = "CS4271", .stream_name = "CS4271 HiFi", - .platform_name = "ep93xx-i2s", - .cpu_dai_name = "ep93xx-i2s", - .codec_name = "spi0.0", - .codec_dai_name = "cs4271-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &edb93xx_ops, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card snd_soc_edb93xx = { From cda80e05c648ff5b702ddbbbf1cd170cc00dba02 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:22 +0900 Subject: [PATCH 225/626] ASoC: cirrus: simone: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/cirrus/simone.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c index cb850530331b..88b082c15c66 100644 --- a/sound/soc/cirrus/simone.c +++ b/sound/soc/cirrus/simone.c @@ -21,13 +21,15 @@ #include +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("ep93xx-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("ep93xx-ac97"))); + static struct snd_soc_dai_link simone_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "ep93xx-ac97", - .codec_dai_name = "ac97-hifi", - .codec_name = "ac97-codec", - .platform_name = "ep93xx-ac97", + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card snd_soc_simone = { From 40989980bf4b9483ad2fb99c58324123a8c74c92 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:28 +0900 Subject: [PATCH 226/626] ASoC: cirrus: snappercl15: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/cirrus/snappercl15.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index dea4909154c8..0b4efcc51232 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c @@ -65,16 +65,19 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic Jack"}, }; +SND_SOC_DAILINK_DEFS(aic23, + DAILINK_COMP_ARRAY(COMP_CPU("ep93xx-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic23-codec.0-001a", + "tlv320aic23-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("ep93xx-i2s"))); + static struct snd_soc_dai_link snappercl15_dai = { .name = "tlv320aic23", .stream_name = "AIC23", - .cpu_dai_name = "ep93xx-i2s", - .codec_dai_name = "tlv320aic23-hifi", - .codec_name = "tlv320aic23-codec.0-001a", - .platform_name = "ep93xx-i2s", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &snappercl15_ops, + SND_SOC_DAILINK_REG(aic23), }; static struct snd_soc_card snd_soc_snappercl15 = { From cf8c3ec87c7259749d079e767b285af5677b411d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:32 +0900 Subject: [PATCH 227/626] ASoC: fsl: efika-audio-fabric: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/efika-audio-fabric.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c index 667f4215dfc0..8f6396faec9b 100644 --- a/sound/soc/fsl/efika-audio-fabric.c +++ b/sound/soc/fsl/efika-audio-fabric.c @@ -29,22 +29,28 @@ #define DRV_NAME "efika-audio-fabric" +SND_SOC_DAILINK_DEFS(analog, + DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("stac9766-codec", + "stac9766-hifi-analog")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("mpc5200-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(iec958, + DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("stac9766-codec", + "stac9766-hifi-IEC958")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("mpc5200-pcm-audio"))); + static struct snd_soc_dai_link efika_fabric_dai[] = { { .name = "AC97", .stream_name = "AC97 Analog", - .codec_dai_name = "stac9766-hifi-analog", - .cpu_dai_name = "mpc5200-psc-ac97.0", - .platform_name = "mpc5200-pcm-audio", - .codec_name = "stac9766-codec", + SND_SOC_DAILINK_REG(analog), }, { .name = "AC97", .stream_name = "AC97 IEC958", - .codec_dai_name = "stac9766-hifi-IEC958", - .cpu_dai_name = "mpc5200-psc-ac97.1", - .platform_name = "mpc5200-pcm-audio", - .codec_name = "stac9766-codec", + SND_SOC_DAILINK_REG(iec958), }, }; From 8337ef4f48876dc4ea9d869a6983c659f65f55bb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:38 +0900 Subject: [PATCH 228/626] ASoC: fsl: imx-spdif: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-spdif.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 4f7f210beb18..6c4dadf60355 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -15,6 +15,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) { struct device_node *spdif_np, *np = pdev->dev.of_node; struct imx_spdif_data *data; + struct snd_soc_dai_link_component *comp; int ret = 0; spdif_np = of_parse_phandle(np, "spdif-controller", 0); @@ -25,17 +26,26 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) { + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!data || !comp) { ret = -ENOMEM; goto end; } + data->dai.cpus = &comp[0]; + data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; + + data->dai.num_cpus = 1; + data->dai.num_codecs = 1; + data->dai.num_platforms = 1; + data->dai.name = "S/PDIF PCM"; data->dai.stream_name = "S/PDIF PCM"; - data->dai.codec_dai_name = "snd-soc-dummy-dai"; - data->dai.codec_name = "snd-soc-dummy"; - data->dai.cpu_of_node = spdif_np; - data->dai.platform_of_node = spdif_np; + data->dai.codecs->dai_name = "snd-soc-dummy-dai"; + data->dai.codecs->name = "snd-soc-dummy"; + data->dai.cpus->of_node = spdif_np; + data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; From 22bda69c650247008a7c3a1035d239194cb95bde Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:44 +0900 Subject: [PATCH 229/626] ASoC: fsl: mx27vis-aic32x4: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/mx27vis-aic32x4.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index 37a4520aef62..38ac4a397742 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c @@ -132,16 +132,19 @@ static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { {"IN3_L", NULL, "Mic Bias"}, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic32x4.0-0018", + "tlv320aic32x4-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); + static struct snd_soc_dai_link mx27vis_aic32x4_dai = { .name = "tlv320aic32x4", .stream_name = "TLV320AIC32X4", - .codec_dai_name = "tlv320aic32x4-hifi", - .platform_name = "imx-ssi.0", - .codec_name = "tlv320aic32x4.0-0018", - .cpu_dai_name = "imx-ssi.0", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &mx27vis_aic32x4_snd_ops, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card mx27vis_aic32x4 = { From 7ca8d923511ac3e17ae92b7cbfa12308dce1ed96 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:50 +0900 Subject: [PATCH 230/626] ASoC: fsl: phycore-ac97: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/phycore-ac97.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/phycore-ac97.c b/sound/soc/fsl/phycore-ac97.c index fe7ba6db7c96..e561f7ff1699 100644 --- a/sound/soc/fsl/phycore-ac97.c +++ b/sound/soc/fsl/phycore-ac97.c @@ -20,15 +20,17 @@ static struct snd_soc_card imx_phycore; static const struct snd_soc_ops imx_phycore_hifi_ops = { }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); + static struct snd_soc_dai_link imx_phycore_dai_ac97[] = { { .name = "HiFi", .stream_name = "HiFi", - .codec_dai_name = "wm9712-hifi", - .codec_name = "wm9712-codec", - .cpu_dai_name = "imx-ssi.0", - .platform_name = "imx-ssi.0", .ops = &imx_phycore_hifi_ops, + SND_SOC_DAILINK_REG(hifi), }, }; From c90cf3d3fb4aee7717eba73f16924394022990bd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:14:59 +0900 Subject: [PATCH 231/626] ASoC: fsl: wm1133-ev1: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/wm1133-ev1.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index aad24ccbef90..52d321bede9c 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c @@ -216,18 +216,20 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) } +SND_SOC_DAILINK_DEFS(ev1, + DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8350-codec.0-0x1a", "wm8350-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); + static struct snd_soc_dai_link wm1133_ev1_dai = { .name = "WM1133-EV1", .stream_name = "Audio", - .cpu_dai_name = "imx-ssi.0", - .codec_dai_name = "wm8350-hifi", - .platform_name = "imx-ssi.0", - .codec_name = "wm8350-codec.0-0x1a", .init = wm1133_ev1_init, .ops = &wm1133_ev1_ops, .symmetric_rates = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(ev1), }; static struct snd_soc_card wm1133_ev1 = { From 893f195104142c0f83e60a91ccada2653bccee2a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:15:11 +0900 Subject: [PATCH 232/626] ASoC: fsl: fsl-asoc-card: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 47 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 60f87a0d99f4..39ea9bda1394 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -200,32 +200,47 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi_fe, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi_be, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY())); + static struct snd_soc_dai_link fsl_asoc_card_dai[] = { /* Default ASoC DAI Link*/ { .name = "HiFi", .stream_name = "HiFi", .ops = &fsl_asoc_card_ops, + SND_SOC_DAILINK_REG(hifi), }, /* DPCM Link between Front-End and Back-End (Optional) */ { .name = "HiFi-ASRC-FE", .stream_name = "HiFi-ASRC-FE", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .dpcm_playback = 1, .dpcm_capture = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hifi_fe), }, { .name = "HiFi-ASRC-BE", .stream_name = "HiFi-ASRC-BE", - .platform_name = "snd-soc-dummy", .be_hw_params_fixup = be_hw_params_fixup, .ops = &fsl_asoc_card_ops, .dpcm_playback = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(hifi_be), }, }; @@ -616,11 +631,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } /* Normal DAI Link */ - priv->dai_link[0].cpu_of_node = cpu_np; - priv->dai_link[0].codec_dai_name = codec_dai_name; + priv->dai_link[0].cpus->of_node = cpu_np; + priv->dai_link[0].codecs->dai_name = codec_dai_name; if (!fsl_asoc_card_is_ac97(priv)) - priv->dai_link[0].codec_of_node = codec_np; + priv->dai_link[0].codecs->of_node = codec_np; else { u32 idx; @@ -631,29 +646,29 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto asrc_fail; } - priv->dai_link[0].codec_name = + priv->dai_link[0].codecs->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ac97-codec.%u", (unsigned int)idx); - if (!priv->dai_link[0].codec_name) { + if (!priv->dai_link[0].codecs->name) { ret = -ENOMEM; goto asrc_fail; } } - priv->dai_link[0].platform_of_node = cpu_np; + priv->dai_link[0].platforms->of_node = cpu_np; priv->dai_link[0].dai_fmt = priv->dai_fmt; priv->card.num_links = 1; if (asrc_pdev) { /* DPCM DAI Links only if ASRC exsits */ - priv->dai_link[1].cpu_of_node = asrc_np; - priv->dai_link[1].platform_of_node = asrc_np; - priv->dai_link[2].codec_dai_name = codec_dai_name; - priv->dai_link[2].codec_of_node = codec_np; - priv->dai_link[2].codec_name = - priv->dai_link[0].codec_name; - priv->dai_link[2].cpu_of_node = cpu_np; + priv->dai_link[1].cpus->of_node = asrc_np; + priv->dai_link[1].platforms->of_node = asrc_np; + priv->dai_link[2].codecs->dai_name = codec_dai_name; + priv->dai_link[2].codecs->of_node = codec_np; + priv->dai_link[2].codecs->name = + priv->dai_link[0].codecs->name; + priv->dai_link[2].cpus->of_node = cpu_np; priv->dai_link[2].dai_fmt = priv->dai_fmt; priv->card.num_links = 3; From 6aa7b4091d0bd3866d42e368ef32674aa1c155cc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:15:25 +0900 Subject: [PATCH 233/626] ASoC: fsl: mpc8610_hpcd/p1022_ds/p1022_rdk: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. mpc8610_hpcd/p1022_ds/p1022_rdk are sharing fsl_asoc_get_dma_channel() which setups platform. We need to update these by 1 patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_utils.c | 2 +- sound/soc/fsl/mpc8610_hpcd.c | 33 ++++++++++++++++++++++++++++----- sound/soc/fsl/p1022_ds.c | 36 ++++++++++++++++++++++++++++++------ sound/soc/fsl/p1022_rdk.c | 35 +++++++++++++++++++++++++++++------ 4 files changed, 88 insertions(+), 18 deletions(-) diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index 040d06b89f00..9bab202569af 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c @@ -57,7 +57,7 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, of_node_put(dma_channel_np); return ret; } - snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%pOFn", + snprintf((char *)dai->platforms->name, DAI_NAME_SIZE, "%llx.%pOFn", (unsigned long long) res.start, dma_channel_np); iprop = of_get_property(dma_channel_np, "cell-index", NULL); diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index f6261a3eeb0f..23617eb09ba1 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -189,6 +189,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; struct mpc8610_hpcd_data *machine_data; + struct snd_soc_dai_link_component *comp; int ret = -ENODEV; const char *sprop; const u32 *iprop; @@ -206,14 +207,36 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) goto error_alloc; } - machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); + comp = devm_kzalloc(&pdev->dev, 6 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto error_alloc; + } + + machine_data->dai[0].cpus = &comp[0]; + machine_data->dai[0].codecs = &comp[1]; + machine_data->dai[0].platforms = &comp[2]; + + machine_data->dai[0].num_cpus = 1; + machine_data->dai[0].num_codecs = 1; + machine_data->dai[0].num_platforms = 1; + + machine_data->dai[1].cpus = &comp[3]; + machine_data->dai[1].codecs = &comp[4]; + machine_data->dai[1].platforms = &comp[5]; + + machine_data->dai[1].num_cpus = 1; + machine_data->dai[1].num_codecs = 1; + machine_data->dai[1].num_platforms = 1; + + machine_data->dai[0].cpus->dai_name = dev_name(&ssi_pdev->dev); machine_data->dai[0].ops = &mpc8610_hpcd_ops; /* ASoC core can match codec with device node */ - machine_data->dai[0].codec_of_node = codec_np; + machine_data->dai[0].codecs->of_node = codec_np; /* The DAI name from the codec (snd_soc_dai_driver.name) */ - machine_data->dai[0].codec_dai_name = "cs4270-hifi"; + machine_data->dai[0].codecs->dai_name = "cs4270-hifi"; /* We register two DAIs per SSI, one for playback and the other for * capture. Currently, we only support codecs that have one DAI for @@ -306,7 +329,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } /* Find the playback DMA channel to use. */ - machine_data->dai[0].platform_name = machine_data->platform_name[0]; + machine_data->dai[0].platforms->name = machine_data->platform_name[0]; ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0], &machine_data->dma_channel_id[0], @@ -317,7 +340,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } /* Find the capture DMA channel to use. */ - machine_data->dai[1].platform_name = machine_data->platform_name[1]; + machine_data->dai[1].platforms->name = machine_data->platform_name[1]; ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1], &machine_data->dma_channel_id[1], diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 80384f70878d..6114b01b90f7 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -199,6 +199,7 @@ static int p1022_ds_probe(struct platform_device *pdev) struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; struct machine_data *mdata; + struct snd_soc_dai_link_component *comp; int ret = -ENODEV; const char *sprop; const u32 *iprop; @@ -216,11 +217,34 @@ static int p1022_ds_probe(struct platform_device *pdev) goto error_put; } - mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); + comp = devm_kzalloc(&pdev->dev, 6 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto error_put; + } + + mdata->dai[0].cpus = &comp[0]; + mdata->dai[0].codecs = &comp[1]; + mdata->dai[0].platforms = &comp[2]; + + mdata->dai[0].num_cpus = 1; + mdata->dai[0].num_codecs = 1; + mdata->dai[0].num_platforms = 1; + + mdata->dai[1].cpus = &comp[3]; + mdata->dai[1].codecs = &comp[4]; + mdata->dai[1].platforms = &comp[5]; + + mdata->dai[1].num_cpus = 1; + mdata->dai[1].num_codecs = 1; + mdata->dai[1].num_platforms = 1; + + + mdata->dai[0].cpus->dai_name = dev_name(&ssi_pdev->dev); mdata->dai[0].ops = &p1022_ds_ops; /* ASoC core can match codec with device node */ - mdata->dai[0].codec_of_node = codec_np; + mdata->dai[0].codecs->of_node = codec_np; /* We register two DAIs per SSI, one for playback and the other for * capture. We support codecs that have separate DAIs for both playback @@ -229,8 +253,8 @@ static int p1022_ds_probe(struct platform_device *pdev) memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link)); /* The DAI names from the codec (snd_soc_dai_driver.name) */ - mdata->dai[0].codec_dai_name = "wm8776-hifi-playback"; - mdata->dai[1].codec_dai_name = "wm8776-hifi-capture"; + mdata->dai[0].codecs->dai_name = "wm8776-hifi-playback"; + mdata->dai[1].codecs->dai_name = "wm8776-hifi-capture"; /* Get the device ID */ iprop = of_get_property(np, "cell-index", NULL); @@ -316,7 +340,7 @@ static int p1022_ds_probe(struct platform_device *pdev) } /* Find the playback DMA channel to use. */ - mdata->dai[0].platform_name = mdata->platform_name[0]; + mdata->dai[0].platforms->name = mdata->platform_name[0]; ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], &mdata->dma_channel_id[0], &mdata->dma_id[0]); @@ -326,7 +350,7 @@ static int p1022_ds_probe(struct platform_device *pdev) } /* Find the capture DMA channel to use. */ - mdata->dai[1].platform_name = mdata->platform_name[1]; + mdata->dai[1].platforms->name = mdata->platform_name[1]; ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1], &mdata->dma_channel_id[1], &mdata->dma_id[1]); diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c index 1c32c2d8c6b0..72687235c0ae 100644 --- a/sound/soc/fsl/p1022_rdk.c +++ b/sound/soc/fsl/p1022_rdk.c @@ -203,6 +203,7 @@ static int p1022_rdk_probe(struct platform_device *pdev) struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; struct machine_data *mdata; + struct snd_soc_dai_link_component *comp; const u32 *iprop; int ret; @@ -219,11 +220,33 @@ static int p1022_rdk_probe(struct platform_device *pdev) goto error_put; } - mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); + comp = devm_kzalloc(&pdev->dev, 6 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto error_put; + } + + mdata->dai[0].cpus = &comp[0]; + mdata->dai[0].codecs = &comp[1]; + mdata->dai[0].platforms = &comp[2]; + + mdata->dai[0].num_cpus = 1; + mdata->dai[0].num_codecs = 1; + mdata->dai[0].num_platforms = 1; + + mdata->dai[1].cpus = &comp[3]; + mdata->dai[1].codecs = &comp[4]; + mdata->dai[1].platforms = &comp[5]; + + mdata->dai[1].num_cpus = 1; + mdata->dai[1].num_codecs = 1; + mdata->dai[1].num_platforms = 1; + + mdata->dai[0].cpus->dai_name = dev_name(&ssi_pdev->dev); mdata->dai[0].ops = &p1022_rdk_ops; /* ASoC core can match codec with device node */ - mdata->dai[0].codec_of_node = codec_np; + mdata->dai[0].codecs->of_node = codec_np; /* * We register two DAIs per SSI, one for playback and the other for @@ -233,8 +256,8 @@ static int p1022_rdk_probe(struct platform_device *pdev) memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link)); /* The DAI names from the codec (snd_soc_dai_driver.name) */ - mdata->dai[0].codec_dai_name = "wm8960-hifi"; - mdata->dai[1].codec_dai_name = mdata->dai[0].codec_dai_name; + mdata->dai[0].codecs->dai_name = "wm8960-hifi"; + mdata->dai[1].codecs->dai_name = mdata->dai[0].codecs->dai_name; /* * Configure the SSI for I2S slave mode. Older device trees have @@ -266,7 +289,7 @@ static int p1022_rdk_probe(struct platform_device *pdev) } /* Find the playback DMA channel to use. */ - mdata->dai[0].platform_name = mdata->platform_name[0]; + mdata->dai[0].platforms->name = mdata->platform_name[0]; ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], &mdata->dma_channel_id[0], &mdata->dma_id[0]); @@ -277,7 +300,7 @@ static int p1022_rdk_probe(struct platform_device *pdev) } /* Find the capture DMA channel to use. */ - mdata->dai[1].platform_name = mdata->platform_name[1]; + mdata->dai[1].platforms->name = mdata->platform_name[1]; ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1], &mdata->dma_channel_id[1], &mdata->dma_id[1]); From 35f6d3025fa8bd75048ccaff5e51ea5446177c24 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:15:32 +0900 Subject: [PATCH 234/626] ASoC: fsl: imx-es8328: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-es8328.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index c9d8739b04a9..15a27a2cd0ca 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -74,6 +74,7 @@ static int imx_es8328_probe(struct platform_device *pdev) struct device_node *ssi_np = NULL, *codec_np = NULL; struct platform_device *ssi_pdev; struct imx_es8328_data *data; + struct snd_soc_dai_link_component *comp; u32 int_port, ext_port; int ret; struct device *dev = &pdev->dev; @@ -147,16 +148,30 @@ static int imx_es8328_probe(struct platform_device *pdev) goto fail; } + comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto fail; + } + data->dev = dev; data->jack_gpio = of_get_named_gpio(pdev->dev.of_node, "jack-gpio", 0); + data->dai.cpus = &comp[0]; + data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; + + data->dai.num_cpus = 1; + data->dai.num_codecs = 1; + data->dai.num_platforms = 1; + data->dai.name = "hifi"; data->dai.stream_name = "hifi"; - data->dai.codec_dai_name = "es8328-hifi-analog"; - data->dai.codec_of_node = codec_np; - data->dai.cpu_of_node = ssi_np; - data->dai.platform_of_node = ssi_np; + data->dai.codecs->dai_name = "es8328-hifi-analog"; + data->dai.codecs->of_node = codec_np; + data->dai.cpus->of_node = ssi_np; + data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_es8328_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; From 3219d9c734627cdf9beee3fd2d136e8fbacb5fcd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:15:54 +0900 Subject: [PATCH 235/626] ASoC: fsl: eukrea-tlv320: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/eukrea-tlv320.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index d648268cb454..6f3b768489f6 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -61,13 +61,18 @@ static const struct snd_soc_ops eukrea_tlv320_snd_ops = { .hw_params = eukrea_tlv320_hw_params, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", - .codec_dai_name = "tlv320aic23-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &eukrea_tlv320_snd_ops, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card eukrea_tlv320 = { @@ -104,7 +109,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) codec_np = of_parse_phandle(ssi_np, "codec-handle", 0); if (codec_np) - eukrea_tlv320_dai.codec_of_node = codec_np; + eukrea_tlv320_dai.codecs->of_node = codec_np; else dev_err(&pdev->dev, "codec-handle node missing or invalid.\n"); @@ -128,12 +133,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) int_port--; ext_port--; - eukrea_tlv320_dai.cpu_of_node = ssi_np; - eukrea_tlv320_dai.platform_of_node = ssi_np; + eukrea_tlv320_dai.cpus->of_node = ssi_np; + eukrea_tlv320_dai.platforms->of_node = ssi_np; } else { - eukrea_tlv320_dai.cpu_dai_name = "imx-ssi.0"; - eukrea_tlv320_dai.platform_name = "imx-ssi.0"; - eukrea_tlv320_dai.codec_name = "tlv320aic23-codec.0-001a"; + eukrea_tlv320_dai.cpus->dai_name = "imx-ssi.0"; + eukrea_tlv320_dai.platforms->name = "imx-ssi.0"; + eukrea_tlv320_dai.codecs->name = "tlv320aic23-codec.0-001a"; eukrea_tlv320.name = "cpuimx-audio"; } From 3026ef68d2c508c9c7c88378907c015710eaf90b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:02 +0900 Subject: [PATCH 236/626] ASoC: fsl: imx-sgtl5000: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-sgtl5000.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index bf8597f57dce..15e8b9343c35 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -55,6 +55,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) struct platform_device *ssi_pdev; struct i2c_client *codec_dev; struct imx_sgtl5000_data *data = NULL; + struct snd_soc_dai_link_component *comp; int int_port, ext_port; int ret; @@ -122,6 +123,12 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) goto fail; } + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto fail; + } + data->codec_clk = clk_get(&codec_dev->dev, NULL); if (IS_ERR(data->codec_clk)) { ret = PTR_ERR(data->codec_clk); @@ -130,12 +137,20 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) data->clk_frequency = clk_get_rate(data->codec_clk); + data->dai.cpus = &comp[0]; + data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; + + data->dai.num_cpus = 1; + data->dai.num_codecs = 1; + data->dai.num_platforms = 1; + data->dai.name = "HiFi"; data->dai.stream_name = "HiFi"; - data->dai.codec_dai_name = "sgtl5000"; - data->dai.codec_of_node = codec_np; - data->dai.cpu_of_node = ssi_np; - data->dai.platform_of_node = ssi_np; + data->dai.codecs->dai_name = "sgtl5000"; + data->dai.codecs->of_node = codec_np; + data->dai.cpus->of_node = ssi_np; + data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_sgtl5000_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; From 8a147e503dd622fe744759bf6199b2a6da45e893 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:08 +0900 Subject: [PATCH 237/626] ASoC: fsl: imx-mc13783: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-mc13783.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index 545815a27074..2b679680c93f 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c @@ -46,17 +46,19 @@ static const struct snd_soc_ops imx_mc13783_hifi_ops = { .hw_params = imx_mc13783_hifi_hw_params, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("mc13783-codec", "mc13783-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); + static struct snd_soc_dai_link imx_mc13783_dai_mc13783[] = { { .name = "MC13783", .stream_name = "Sound", - .codec_dai_name = "mc13783-hifi", - .codec_name = "mc13783-codec", - .cpu_dai_name = "imx-ssi.0", - .platform_name = "imx-ssi.0", .ops = &imx_mc13783_hifi_ops, .symmetric_rates = 1, .dai_fmt = FMT_SSI, + SND_SOC_DAILINK_REG(hifi), }, }; From 61c29313cb812a6de3dc7bfd7baa3d20cf7e3e83 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:14 +0900 Subject: [PATCH 238/626] ASoC: fsl: pcm030-audio-fabric: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index a7fe4ad25c52..af3c3b90c0ac 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -23,20 +23,26 @@ struct pcm030_audio_data { struct platform_device *codec_device; }; +SND_SOC_DAILINK_DEFS(analog, + DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(iec958, + DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link pcm030_fabric_dai[] = { { .name = "AC97.0", .stream_name = "AC97 Analog", - .codec_dai_name = "wm9712-hifi", - .cpu_dai_name = "mpc5200-psc-ac97.0", - .codec_name = "wm9712-codec", + SND_SOC_DAILINK_REG(analog), }, { .name = "AC97.1", .stream_name = "AC97 IEC958", - .codec_dai_name = "wm9712-aux", - .cpu_dai_name = "mpc5200-psc-ac97.1", - .codec_name = "wm9712-codec", + SND_SOC_DAILINK_REG(iec958), }, }; @@ -76,7 +82,7 @@ static int pcm030_fabric_probe(struct platform_device *op) } for_each_card_prelinks(card, i, dai_link) - dai_link->platform_of_node = platform_np; + dai_link->platforms->of_node = platform_np; ret = request_module("snd-soc-wm9712"); if (ret) From 79782e283ed3df04bfb77129091f1d6726987f1e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:20 +0900 Subject: [PATCH 239/626] ASoC: fsl: imx-audmix: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 45 +++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 9aaf3e5b45b9..9e1cb18859ce 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -205,6 +205,15 @@ static int imx_audmix_probe(struct platform_device *pdev) return -ENOMEM; for (i = 0; i < num_dai; i++) { + struct snd_soc_dai_link_component *dlc; + + /* for CPU/Codec/Platform x 2 */ + dlc = devm_kzalloc(&pdev->dev, 6 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) { + dev_err(&pdev->dev, "failed to allocate dai_link\n"); + return -ENOMEM; + } + ret = of_parse_phandle_with_args(audmix_np, "dais", NULL, i, &args); if (ret < 0) { @@ -231,13 +240,21 @@ static int imx_audmix_probe(struct platform_device *pdev) dai_name, "CPU-Capture"); } + priv->dai[i].cpus = &dlc[0]; + priv->dai[i].codecs = &dlc[1]; + priv->dai[i].platforms = &dlc[2]; + + priv->dai[i].num_cpus = 1; + priv->dai[i].num_codecs = 1; + priv->dai[i].num_platforms = 1; + priv->dai[i].name = dai_name; priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; - priv->dai[i].codec_dai_name = "snd-soc-dummy-dai"; - priv->dai[i].codec_name = "snd-soc-dummy"; - priv->dai[i].cpu_of_node = args.np; - priv->dai[i].cpu_dai_name = dev_name(&cpu_pdev->dev); - priv->dai[i].platform_of_node = args.np; + priv->dai[i].codecs->dai_name = "snd-soc-dummy-dai"; + priv->dai[i].codecs->name = "snd-soc-dummy"; + priv->dai[i].cpus->of_node = args.np; + priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); + priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -252,12 +269,20 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); + priv->dai[num_dai + i].cpus = &dlc[3]; + priv->dai[num_dai + i].codecs = &dlc[4]; + priv->dai[num_dai + i].platforms = &dlc[5]; + + priv->dai[num_dai + i].num_cpus = 1; + priv->dai[num_dai + i].num_codecs = 1; + priv->dai[num_dai + i].num_platforms = 1; + priv->dai[num_dai + i].name = be_name; - priv->dai[num_dai + i].codec_dai_name = "snd-soc-dummy-dai"; - priv->dai[num_dai + i].codec_name = "snd-soc-dummy"; - priv->dai[num_dai + i].cpu_of_node = audmix_np; - priv->dai[num_dai + i].cpu_dai_name = be_name; - priv->dai[num_dai + i].platform_name = "snd-soc-dummy"; + priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; + priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; + priv->dai[num_dai + i].cpus->of_node = audmix_np; + priv->dai[num_dai + i].cpus->dai_name = be_name; + priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; From 7c5cbcfe966b4952ab69a1f6c8f06806d9396e9d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:26 +0900 Subject: [PATCH 240/626] ASoC: jz4740: qi_lb60: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/jz4740/qi_lb60.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c index 53586999fcaa..45bdcaf6da98 100644 --- a/sound/soc/jz4740/qi_lb60.c +++ b/sound/soc/jz4740/qi_lb60.c @@ -49,15 +49,17 @@ static const struct snd_soc_dapm_route qi_lb60_routes[] = { {"Speaker", NULL, "ROUT"}, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("jz4740-i2s")), + DAILINK_COMP_ARRAY(COMP_CODEC("jz4740-codec", "jz4740-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("jz4740-i2s"))); + static struct snd_soc_dai_link qi_lb60_dai = { .name = "jz4740", .stream_name = "jz4740", - .cpu_dai_name = "jz4740-i2s", - .platform_name = "jz4740-i2s", - .codec_dai_name = "jz4740-hifi", - .codec_name = "jz4740-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card qi_lb60_card = { From c84836d7f6509141d5be31cc7a1028228fe0545a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:32 +0900 Subject: [PATCH 241/626] ASoC: meson: axg-card: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 57 ++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index db0a7fc18928..fb03258d00ae 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -115,7 +115,7 @@ static void axg_card_clean_references(struct axg_card *priv) if (card->dai_link) { for_each_card_prelinks(card, i, link) { - of_node_put(link->cpu_of_node); + of_node_put(link->cpus->of_node); for_each_link_codecs(link, j, codec) of_node_put(codec->of_node); } @@ -254,6 +254,7 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card, struct axg_card *priv = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link *pad = &card->dai_link[*index]; struct snd_soc_dai_link *lb; + struct snd_soc_dai_link_component *dlc; int ret; /* extend links */ @@ -267,11 +268,20 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card, if (!lb->name) return -ENOMEM; + dlc = devm_kzalloc(card->dev, 2 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return -ENOMEM; + + lb->cpus = &dlc[0]; + lb->codecs = &dlc[1]; + lb->num_cpus = 1; + lb->num_codecs = 1; + lb->stream_name = lb->name; - lb->cpu_of_node = pad->cpu_of_node; - lb->cpu_dai_name = "TDM Loopback"; - lb->codec_name = "snd-soc-dummy"; - lb->codec_dai_name = "snd-soc-dummy-dai"; + lb->cpus->of_node = pad->cpus->of_node; + lb->cpus->dai_name = "TDM Loopback"; + lb->codecs->name = "snd-soc-dummy"; + lb->codecs->dai_name = "snd-soc-dummy-dai"; lb->dpcm_capture = 1; lb->no_pcm = 1; lb->ops = &axg_card_tdm_be_ops; @@ -284,7 +294,7 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card, * axg_card_clean_references() will iterate over this link, * make sure the node count is balanced */ - of_node_get(lb->cpu_of_node); + of_node_get(lb->cpus->of_node); /* Let add_links continue where it should */ *index += 1; @@ -426,7 +436,7 @@ static int axg_card_parse_tdm(struct snd_soc_card *card, /* Setup tdm link */ link->ops = &axg_card_tdm_be_ops; link->init = axg_card_tdm_dai_init; - link->dai_fmt = axg_card_parse_daifmt(node, link->cpu_of_node); + link->dai_fmt = axg_card_parse_daifmt(node, link->cpus->of_node); of_property_read_u32(node, "mclk-fs", &be->mclk_fs); @@ -499,12 +509,21 @@ static int axg_card_set_fe_link(struct snd_soc_card *card, struct device_node *node, bool is_playback) { + struct snd_soc_dai_link_component *codec; + + codec = devm_kzalloc(card->dev, sizeof(*codec), GFP_KERNEL); + if (!codec) + return -ENOMEM; + + link->codecs = codec; + link->num_codecs = 1; + link->dynamic = 1; link->dpcm_merged_format = 1; link->dpcm_merged_chan = 1; link->dpcm_merged_rate = 1; - link->codec_dai_name = "snd-soc-dummy-dai"; - link->codec_name = "snd-soc-dummy"; + link->codecs->dai_name = "snd-soc-dummy-dai"; + link->codecs->name = "snd-soc-dummy"; if (is_playback) link->dpcm_playback = 1; @@ -538,16 +557,24 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, int *index) { struct snd_soc_dai_link *dai_link = &card->dai_link[*index]; + struct snd_soc_dai_link_component *cpu; int ret; - ret = axg_card_parse_dai(card, np, &dai_link->cpu_of_node, - &dai_link->cpu_dai_name); + cpu = devm_kzalloc(card->dev, sizeof(*cpu), GFP_KERNEL); + if (!cpu) + return -ENOMEM; + + dai_link->cpus = cpu; + dai_link->num_cpus = 1; + + ret = axg_card_parse_dai(card, np, &dai_link->cpus->of_node, + &dai_link->cpus->dai_name); if (ret) return ret; - if (axg_card_cpu_is_playback_fe(dai_link->cpu_of_node)) + if (axg_card_cpu_is_playback_fe(dai_link->cpus->of_node)) ret = axg_card_set_fe_link(card, dai_link, np, true); - else if (axg_card_cpu_is_capture_fe(dai_link->cpu_of_node)) + else if (axg_card_cpu_is_capture_fe(dai_link->cpus->of_node)) ret = axg_card_set_fe_link(card, dai_link, np, false); else ret = axg_card_set_be_link(card, dai_link, np); @@ -555,9 +582,9 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, if (ret) return ret; - if (axg_card_cpu_is_tdm_iface(dai_link->cpu_of_node)) + if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node)) ret = axg_card_parse_tdm(card, np, index); - else if (axg_card_cpu_is_codec(dai_link->cpu_of_node)) + else if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) dai_link->params = &codec_params; return ret; From 49cb448846f57227a9758dc71a19ce1e24ddbbdd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:37 +0900 Subject: [PATCH 242/626] ASoC: mxs: mxs-sgtl5000: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-sgtl5000.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 2b3f2408301a..459fced603b0 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -75,21 +75,32 @@ static const struct snd_soc_ops mxs_sgtl5000_hifi_ops = { #define MXS_SGTL5000_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ SND_SOC_DAIFMT_CBS_CFS) + +SND_SOC_DAILINK_DEFS(hifi_tx, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi_rx, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { { .name = "HiFi Tx", .stream_name = "HiFi Playback", - .codec_dai_name = "sgtl5000", .dai_fmt = MXS_SGTL5000_DAI_FMT, .ops = &mxs_sgtl5000_hifi_ops, .playback_only = true, + SND_SOC_DAILINK_REG(hifi_tx), }, { .name = "HiFi Rx", .stream_name = "HiFi Capture", - .codec_dai_name = "sgtl5000", .dai_fmt = MXS_SGTL5000_DAI_FMT, .ops = &mxs_sgtl5000_hifi_ops, .capture_only = true, + SND_SOC_DAILINK_REG(hifi_rx), }, }; @@ -124,12 +135,12 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) } for (i = 0; i < 2; i++) { - mxs_sgtl5000_dai[i].codec_name = NULL; - mxs_sgtl5000_dai[i].codec_of_node = codec_np; - mxs_sgtl5000_dai[i].cpu_dai_name = NULL; - mxs_sgtl5000_dai[i].cpu_of_node = saif_np[i]; - mxs_sgtl5000_dai[i].platform_name = NULL; - mxs_sgtl5000_dai[i].platform_of_node = saif_np[i]; + mxs_sgtl5000_dai[i].codecs->name = NULL; + mxs_sgtl5000_dai[i].codecs->of_node = codec_np; + mxs_sgtl5000_dai[i].cpus->dai_name = NULL; + mxs_sgtl5000_dai[i].cpus->of_node = saif_np[i]; + mxs_sgtl5000_dai[i].platforms->name = NULL; + mxs_sgtl5000_dai[i].platforms->of_node = saif_np[i]; } of_node_put(codec_np); From 26d8d4b21f9ec7ed2a2e236b048961554ea9bbeb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:44 +0900 Subject: [PATCH 243/626] ASoC: nuc900: nuc900-audio: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/nuc900/nuc900-audio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c index 2f6e6fd6e05c..f207d3e956fa 100644 --- a/sound/soc/nuc900/nuc900-audio.c +++ b/sound/soc/nuc900/nuc900-audio.c @@ -21,13 +21,15 @@ #include "nuc900-audio.h" +SND_SOC_DAILINK_DEFS(ac97, + DAILINK_COMP_ARRAY(COMP_CPU("nuc900-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("nuc900-pcm-audio"))); + static struct snd_soc_dai_link nuc900evb_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "nuc900-ac97", - .codec_dai_name = "ac97-hifi", - .codec_name = "ac97-codec", - .platform_name = "nuc900-pcm-audio", + SND_SOC_DAILINK_REG(ac97), }; static struct snd_soc_card nuc900evb_audio_machine = { From fa350b770b57d6e17b73d259bfec7e40099f7261 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:51 +0900 Subject: [PATCH 244/626] ASoC: qcom: storm: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/storm.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c index a9fa972466ad..672edee2ea93 100644 --- a/sound/soc/qcom/storm.c +++ b/sound/soc/qcom/storm.c @@ -61,11 +61,16 @@ static const struct snd_soc_ops storm_soc_ops = { .hw_params = storm_ops_hw_params, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link storm_dai_link = { .name = "Primary", .stream_name = "Primary", - .codec_dai_name = "HiFi", .ops = &storm_soc_ops, + SND_SOC_DAILINK_REG(hifi), }; static int storm_parse_of(struct snd_soc_card *card) @@ -73,15 +78,15 @@ static int storm_parse_of(struct snd_soc_card *card) struct snd_soc_dai_link *dai_link = card->dai_link; struct device_node *np = card->dev->of_node; - dai_link->cpu_of_node = of_parse_phandle(np, "cpu", 0); - if (!dai_link->cpu_of_node) { + dai_link->cpus->of_node = of_parse_phandle(np, "cpu", 0); + if (!dai_link->cpus->of_node) { dev_err(card->dev, "error getting cpu phandle\n"); return -EINVAL; } - dai_link->platform_of_node = dai_link->cpu_of_node; + dai_link->platforms->of_node = dai_link->cpus->of_node; - dai_link->codec_of_node = of_parse_phandle(np, "codec", 0); - if (!dai_link->codec_of_node) { + dai_link->codecs->of_node = of_parse_phandle(np, "codec", 0); + if (!dai_link->codecs->of_node) { dev_err(card->dev, "error getting codec phandle\n"); return -EINVAL; } From 1e36ea360ab98e9c20329a3d9364705d1347e411 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:16:58 +0900 Subject: [PATCH 245/626] ASoC: qcom: common: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/common.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 5661025e8cec..c7a878507220 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -14,6 +14,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) struct device *dev = card->dev; struct snd_soc_dai_link *link; struct of_phandle_args args; + struct snd_soc_dai_link_component *dlc; int ret, num_links; ret = snd_soc_of_parse_card_name(card, "model"); @@ -40,6 +41,17 @@ int qcom_snd_parse_of(struct snd_soc_card *card) card->num_links = num_links; link = card->dai_link; + + dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return -ENOMEM; + + link->cpus = &dlc[0]; + link->platforms = &dlc[1]; + + link->num_cpus = 1; + link->num_platforms = 1; + for_each_child_of_node(dev->of_node, np) { cpu = of_get_child_by_name(np, "cpu"); platform = of_get_child_by_name(np, "platform"); @@ -57,20 +69,20 @@ int qcom_snd_parse_of(struct snd_soc_card *card) dev_err(card->dev, "error getting cpu phandle\n"); goto err; } - link->cpu_of_node = args.np; + link->cpus->of_node = args.np; link->id = args.args[0]; - ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); + ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); if (ret) { dev_err(card->dev, "error getting cpu dai name\n"); goto err; } if (codec && platform) { - link->platform_of_node = of_parse_phandle(platform, + link->platforms->of_node = of_parse_phandle(platform, "sound-dai", 0); - if (!link->platform_of_node) { + if (!link->platforms->of_node) { dev_err(card->dev, "platform dai not found\n"); ret = -EINVAL; goto err; @@ -84,9 +96,16 @@ int qcom_snd_parse_of(struct snd_soc_card *card) link->no_pcm = 1; link->ignore_pmdown_time = 1; } else { - link->platform_of_node = link->cpu_of_node; - link->codec_dai_name = "snd-soc-dummy-dai"; - link->codec_name = "snd-soc-dummy"; + dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return -ENOMEM; + + link->codecs = dlc; + link->num_codecs = 1; + + link->platforms->of_node = link->cpus->of_node; + link->codecs->dai_name = "snd-soc-dummy-dai"; + link->codecs->name = "snd-soc-dummy"; link->dynamic = 1; } From 98b232ca9e0e7fb0f3be80653f647c8ce369556d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:17:04 +0900 Subject: [PATCH 246/626] ASoC: qcom: apq8016_sbc: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/apq8016_sbc.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 4b559932adc3..717542c61d04 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -126,6 +126,7 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) struct snd_soc_dai_link *link; struct device_node *np, *codec, *cpu, *node = dev->of_node; struct apq8016_sbc_data *data; + struct snd_soc_dai_link_component *dlc; int ret, num_links; ret = snd_soc_of_parse_card_name(card, "qcom,model"); @@ -158,6 +159,16 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) link = data->dai_link; + dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return ERR_PTR(-ENOMEM); + + link->cpus = &dlc[0]; + link->platforms = &dlc[1]; + + link->num_cpus = 1; + link->num_platforms = 1; + for_each_child_of_node(node, np) { cpu = of_get_child_by_name(np, "cpu"); codec = of_get_child_by_name(np, "codec"); @@ -168,14 +179,14 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) goto error; } - link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); - if (!link->cpu_of_node) { + link->cpus->of_node = of_parse_phandle(cpu, "sound-dai", 0); + if (!link->cpus->of_node) { dev_err(card->dev, "error getting cpu phandle\n"); ret = -EINVAL; goto error; } - ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); + ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); if (ret) { dev_err(card->dev, "error getting cpu dai name\n"); goto error; @@ -188,7 +199,7 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) goto error; } - link->platform_of_node = link->cpu_of_node; + link->platforms->of_node = link->cpus->of_node; ret = of_property_read_string(np, "link-name", &link->name); if (ret) { dev_err(card->dev, "error getting codec dai_link name\n"); From 96a239b7af0f4d502f7a577bd0df9acb715a9ca6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:17:10 +0900 Subject: [PATCH 247/626] ASoC: rockchip: rk3399_gru_sound: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3399_gru_sound.c | 51 +++++++++++++++++++++------ 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index f2a51ae2b674..5e2700283fa8 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -276,56 +276,85 @@ enum { DAILINK_RT5514_DSP, }; +SND_SOC_DAILINK_DEFS(cdndp, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(da7219, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(dmic, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(max98357a, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(rt5514, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(rt5514_dsp, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static const struct snd_soc_dai_link rockchip_dais[] = { [DAILINK_CDNDP] = { .name = "DP", .stream_name = "DP PCM", - .codec_dai_name = "spdif-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(cdndp), }, [DAILINK_DA7219] = { .name = "DA7219", .stream_name = "DA7219 PCM", - .codec_dai_name = "da7219-hifi", .init = rockchip_sound_da7219_init, .ops = &rockchip_sound_da7219_ops, /* set da7219 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(da7219), }, [DAILINK_DMIC] = { .name = "DMIC", .stream_name = "DMIC PCM", - .codec_dai_name = "dmic-hifi", .ops = &rockchip_sound_dmic_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(dmic), }, [DAILINK_MAX98357A] = { .name = "MAX98357A", .stream_name = "MAX98357A PCM", - .codec_dai_name = "HiFi", .ops = &rockchip_sound_max98357a_ops, /* set max98357a as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(max98357a), }, [DAILINK_RT5514] = { .name = "RT5514", .stream_name = "RT5514 PCM", - .codec_dai_name = "rt5514-aif1", .ops = &rockchip_sound_rt5514_ops, /* set rt5514 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(rt5514), }, /* RT5514 DSP for voice wakeup via spi bus */ [DAILINK_RT5514_DSP] = { .name = "RT5514 DSP", .stream_name = "Wake on Voice", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", + SND_SOC_DAILINK_REG(rt5514_dsp), }, }; @@ -507,10 +536,10 @@ static int rockchip_sound_of_parse_dais(struct device *dev, dai = &card->dai_link[card->num_links++]; *dai = rockchip_dais[index]; - if (!dai->codec_name) - dai->codec_of_node = np_codec; - dai->platform_of_node = np_cpu; - dai->cpu_of_node = np_cpu; + if (!dai->codecs->name) + dai->codecs->of_node = np_codec; + dai->platforms->of_node = np_cpu; + dai->cpus->of_node = np_cpu; if (card->num_dapm_routes + rockchip_routes[index].num_routes > num_routes) { From e0d129d4cac049ff21861f5a73506786e34e7f5a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:17:31 +0900 Subject: [PATCH 248/626] ASoC: rockchip: rk3288_hdmi_analog: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3288_hdmi_analog.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c index a472d5eb2950..71ee16d7bde6 100644 --- a/sound/soc/rockchip/rk3288_hdmi_analog.c +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c @@ -151,24 +151,21 @@ static const struct snd_soc_ops rk_ops = { .hw_params = rk_hw_params, }; -static struct snd_soc_dai_link_component rk_codecs[] = { - { }, - { - .name = "hdmi-audio-codec.2.auto", - .dai_name = "i2s-hifi", - }, -}; +SND_SOC_DAILINK_DEFS(audio, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL), + COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link rk_dailink = { .name = "Codecs", .stream_name = "Audio", .init = rk_init, .ops = &rk_ops, - .codecs = rk_codecs, - .num_codecs = ARRAY_SIZE(rk_codecs), /* Set codecs as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(audio), }; static struct snd_soc_card snd_soc_card_rk = { @@ -244,15 +241,15 @@ static int snd_rk_mc_probe(struct platform_device *pdev) return ret; } - rk_dailink.cpu_of_node = of_parse_phandle(np, "rockchip,i2s-controller", + rk_dailink.cpus->of_node = of_parse_phandle(np, "rockchip,i2s-controller", 0); - if (!rk_dailink.cpu_of_node) { + if (!rk_dailink.cpus->of_node) { dev_err(&pdev->dev, "Property 'rockchip,i2s-controller' missing or invalid\n"); return -EINVAL; } - rk_dailink.platform_of_node = rk_dailink.cpu_of_node; + rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; ret = snd_soc_of_parse_audio_routing(card, "rockchip,routing"); if (ret) { From 0209bf2b2a765cd5c705a1f97e8f57895e3b9821 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:17:37 +0900 Subject: [PATCH 249/626] ASoC: rockchip: rockchip_rt5645: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_rt5645.c | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index 881c32498808..e17f01635bba 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -135,15 +135,20 @@ static const struct snd_soc_ops rk_aif1_ops = { .hw_params = rk_aif1_hw_params, }; +SND_SOC_DAILINK_DEFS(pcm, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link rk_dailink = { .name = "rt5645", .stream_name = "rt5645 PCM", - .codec_dai_name = "rt5645-aif1", .init = rk_init, .ops = &rk_aif1_ops, /* set rt5645 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(pcm), }; static struct snd_soc_card snd_soc_card_rk = { @@ -168,24 +173,24 @@ static int snd_rk_mc_probe(struct platform_device *pdev) /* register the soc card */ card->dev = &pdev->dev; - rk_dailink.codec_of_node = of_parse_phandle(np, + rk_dailink.codecs->of_node = of_parse_phandle(np, "rockchip,audio-codec", 0); - if (!rk_dailink.codec_of_node) { + if (!rk_dailink.codecs->of_node) { dev_err(&pdev->dev, "Property 'rockchip,audio-codec' missing or invalid\n"); return -EINVAL; } - rk_dailink.cpu_of_node = of_parse_phandle(np, + rk_dailink.cpus->of_node = of_parse_phandle(np, "rockchip,i2s-controller", 0); - if (!rk_dailink.cpu_of_node) { + if (!rk_dailink.cpus->of_node) { dev_err(&pdev->dev, "Property 'rockchip,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto put_codec_of_node; } - rk_dailink.platform_of_node = rk_dailink.cpu_of_node; + rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; ret = snd_soc_of_parse_card_name(card, "rockchip,model"); if (ret) { @@ -204,21 +209,21 @@ static int snd_rk_mc_probe(struct platform_device *pdev) return ret; put_cpu_of_node: - of_node_put(rk_dailink.cpu_of_node); - rk_dailink.cpu_of_node = NULL; + of_node_put(rk_dailink.cpus->of_node); + rk_dailink.cpus->of_node = NULL; put_codec_of_node: - of_node_put(rk_dailink.codec_of_node); - rk_dailink.codec_of_node = NULL; + of_node_put(rk_dailink.codecs->of_node); + rk_dailink.codecs->of_node = NULL; return ret; } static int snd_rk_mc_remove(struct platform_device *pdev) { - of_node_put(rk_dailink.cpu_of_node); - rk_dailink.cpu_of_node = NULL; - of_node_put(rk_dailink.codec_of_node); - rk_dailink.codec_of_node = NULL; + of_node_put(rk_dailink.cpus->of_node); + rk_dailink.cpus->of_node = NULL; + of_node_put(rk_dailink.codecs->of_node); + rk_dailink.codecs->of_node = NULL; return 0; } From 8d6975ea3627d3aff2c9c8bb6b6eb84cddef0e07 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:01 +0900 Subject: [PATCH 250/626] ASoC: rockchip: rockchip_max98090: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index 789d6f1e2b5f..fcb5c06a0fe2 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -123,14 +123,19 @@ static const struct snd_soc_ops rk_aif1_ops = { .hw_params = rk_aif1_hw_params, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link rk_dailink = { .name = "max98090", .stream_name = "Audio", - .codec_dai_name = "HiFi", .ops = &rk_aif1_ops, /* set max98090 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(hifi), }; static int rk_98090_headset_init(struct snd_soc_component *component); @@ -184,23 +189,23 @@ static int snd_rk_mc_probe(struct platform_device *pdev) /* register the soc card */ card->dev = &pdev->dev; - rk_dailink.codec_of_node = of_parse_phandle(np, + rk_dailink.codecs->of_node = of_parse_phandle(np, "rockchip,audio-codec", 0); - if (!rk_dailink.codec_of_node) { + if (!rk_dailink.codecs->of_node) { dev_err(&pdev->dev, "Property 'rockchip,audio-codec' missing or invalid\n"); return -EINVAL; } - rk_dailink.cpu_of_node = of_parse_phandle(np, + rk_dailink.cpus->of_node = of_parse_phandle(np, "rockchip,i2s-controller", 0); - if (!rk_dailink.cpu_of_node) { + if (!rk_dailink.cpus->of_node) { dev_err(&pdev->dev, "Property 'rockchip,i2s-controller' missing or invalid\n"); return -EINVAL; } - rk_dailink.platform_of_node = rk_dailink.cpu_of_node; + rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; rk_98090_headset_dev.codec_of_node = of_parse_phandle(np, "rockchip,headset-codec", 0); From a39bb1b740c95d8f0029b280266744897453e8ee Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:06 +0900 Subject: [PATCH 251/626] ASoC: sirf: sirf-audio: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sirf/sirf-audio.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c index f2bc50790f76..ba85ccf1fe19 100644 --- a/sound/soc/sirf/sirf-audio.c +++ b/sound/soc/sirf/sirf-audio.c @@ -61,11 +61,16 @@ static const struct snd_soc_dapm_route intercon[] = { }; /* Digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEFS(sirf, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sirf-audio-codec")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link sirf_audio_dai_link[] = { { .name = "SiRF audio card", .stream_name = "SiRF audio HiFi", - .codec_dai_name = "sirf-audio-codec", + SND_SOC_DAILINK_REG(sirf), }, }; @@ -92,11 +97,11 @@ static int sirf_audio_probe(struct platform_device *pdev) if (sirf_audio_card == NULL) return -ENOMEM; - sirf_audio_dai_link[0].cpu_of_node = + sirf_audio_dai_link[0].cpus->of_node = of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); - sirf_audio_dai_link[0].platform_of_node = + sirf_audio_dai_link[0].platforms->of_node = of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); - sirf_audio_dai_link[0].codec_of_node = + sirf_audio_dai_link[0].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0); sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node, "spk-pa-gpios", 0); From 8ad8d81a0ff66f48a28a6fc795524085ce999111 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:14 +0900 Subject: [PATCH 252/626] ASoC: ux500: mop500: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ux500/mop500.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index c60a57797640..20552e9d9217 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -27,26 +27,30 @@ #include "mop500_ab8500.h" /* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ +SND_SOC_DAILINK_DEFS(link1, + DAILINK_COMP_ARRAY(COMP_CPU("ux500-msp-i2s.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.0")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("ux500-msp-i2s.1"))); + +SND_SOC_DAILINK_DEFS(link2, + DAILINK_COMP_ARRAY(COMP_CPU("ux500-msp-i2s.3")), + DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("ux500-msp-i2s.3"))); + static struct snd_soc_dai_link mop500_dai_links[] = { { .name = "ab8500_0", .stream_name = "ab8500_0", - .cpu_dai_name = "ux500-msp-i2s.1", - .codec_dai_name = "ab8500-codec-dai.0", - .platform_name = "ux500-msp-i2s.1", - .codec_name = "ab8500-codec.0", .init = mop500_ab8500_machine_init, .ops = mop500_ab8500_ops, + SND_SOC_DAILINK_REG(link1), }, { .name = "ab8500_1", .stream_name = "ab8500_1", - .cpu_dai_name = "ux500-msp-i2s.3", - .codec_dai_name = "ab8500-codec-dai.1", - .platform_name = "ux500-msp-i2s.3", - .codec_name = "ab8500-codec.0", .init = NULL, .ops = mop500_ab8500_ops, + SND_SOC_DAILINK_REG(link2), }, }; @@ -63,8 +67,8 @@ static void mop500_of_node_put(void) int i; for (i = 0; i < 2; i++) { - of_node_put(mop500_dai_links[i].cpu_of_node); - of_node_put(mop500_dai_links[i].codec_of_node); + of_node_put(mop500_dai_links[i].cpus->of_node); + of_node_put(mop500_dai_links[i].codecs->of_node); } } @@ -85,12 +89,12 @@ static int mop500_of_probe(struct platform_device *pdev, } for (i = 0; i < 2; i++) { - mop500_dai_links[i].cpu_of_node = msp_np[i]; - mop500_dai_links[i].cpu_dai_name = NULL; - mop500_dai_links[i].platform_of_node = msp_np[i]; - mop500_dai_links[i].platform_name = NULL; - mop500_dai_links[i].codec_of_node = codec_np; - mop500_dai_links[i].codec_name = NULL; + mop500_dai_links[i].cpus->of_node = msp_np[i]; + mop500_dai_links[i].cpus->dai_name = NULL; + mop500_dai_links[i].platforms->of_node = msp_np[i]; + mop500_dai_links[i].platforms->name = NULL; + mop500_dai_links[i].codecs->of_node = codec_np; + mop500_dai_links[i].codecs->name = NULL; } snd_soc_of_parse_card_name(&mop500_card, "stericsson,card-name"); From 950d10e879d4a263ca10ab1ff9657a258208e7b9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:19 +0900 Subject: [PATCH 253/626] ASoC: sunxi: sun4i-codec: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 28d2f7713f8d..161444fe4518 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1305,15 +1305,25 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, { struct snd_soc_dai_link *link = devm_kzalloc(dev, sizeof(*link), GFP_KERNEL); - if (!link) + struct snd_soc_dai_link_component *dlc = devm_kzalloc(dev, + 3 * sizeof(*dlc), GFP_KERNEL); + if (!link || !dlc) return NULL; + link->cpus = &dlc[0]; + link->codecs = &dlc[1]; + link->platforms = &dlc[2]; + + link->num_cpus = 1; + link->num_codecs = 1; + link->num_platforms = 1; + link->name = "cdc"; link->stream_name = "CDC PCM"; - link->codec_dai_name = "Codec"; - link->cpu_dai_name = dev_name(dev); - link->codec_name = dev_name(dev); - link->platform_name = dev_name(dev); + link->codecs->dai_name = "Codec"; + link->cpus->dai_name = dev_name(dev); + link->codecs->name = dev_name(dev); + link->platforms->name = dev_name(dev); link->dai_fmt = SND_SOC_DAIFMT_I2S; *num_links = 1; From f4010b4c8b382c2acb024fd91e2734323e457f98 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:25 +0900 Subject: [PATCH 254/626] ASoC: txx9: txx9aclc-generic: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/txx9/txx9aclc-generic.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c index d0b1e7759968..c5aaad158280 100644 --- a/sound/soc/txx9/txx9aclc-generic.c +++ b/sound/soc/txx9/txx9aclc-generic.c @@ -21,13 +21,15 @@ #include #include "txx9aclc.h" +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("txx9aclc-ac97")), + DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("txx9aclc-pcm-audio"))); + static struct snd_soc_dai_link txx9aclc_generic_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "txx9aclc-ac97", - .codec_dai_name = "ac97-hifi", - .platform_name = "txx9aclc-pcm-audio", - .codec_name = "ac97-codec", + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card txx9aclc_generic_card = { From 9b4f646a3aed26f4cb7f310013d1dda61aab9b47 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:30 +0900 Subject: [PATCH 255/626] ASoC: tegra: tegra_rt5677: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_rt5677.c | 37 +++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c index 7081f15302cc..7edf6c7838f5 100644 --- a/sound/soc/tegra/tegra_rt5677.c +++ b/sound/soc/tegra/tegra_rt5677.c @@ -169,14 +169,19 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(pcm, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5677-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tegra_rt5677_dai = { .name = "RT5677", .stream_name = "RT5677 PCM", - .codec_dai_name = "rt5677-aif1", .init = tegra_rt5677_asoc_init, .ops = &tegra_rt5677_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(pcm), }; static struct snd_soc_card snd_soc_tegra_rt5677 = { @@ -249,24 +254,24 @@ static int tegra_rt5677_probe(struct platform_device *pdev) if (ret) goto err; - tegra_rt5677_dai.codec_of_node = of_parse_phandle(np, + tegra_rt5677_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); - if (!tegra_rt5677_dai.codec_of_node) { + if (!tegra_rt5677_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_rt5677_dai.cpu_of_node = of_parse_phandle(np, + tegra_rt5677_dai.cpus->of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_rt5677_dai.cpu_of_node) { + if (!tegra_rt5677_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err_put_codec_of_node; } - tegra_rt5677_dai.platform_of_node = tegra_rt5677_dai.cpu_of_node; + tegra_rt5677_dai.platforms->of_node = tegra_rt5677_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) @@ -284,12 +289,12 @@ static int tegra_rt5677_probe(struct platform_device *pdev) err_fini_utils: tegra_asoc_utils_fini(&machine->util_data); err_put_cpu_of_node: - of_node_put(tegra_rt5677_dai.cpu_of_node); - tegra_rt5677_dai.cpu_of_node = NULL; - tegra_rt5677_dai.platform_of_node = NULL; + of_node_put(tegra_rt5677_dai.cpus->of_node); + tegra_rt5677_dai.cpus->of_node = NULL; + tegra_rt5677_dai.platforms->of_node = NULL; err_put_codec_of_node: - of_node_put(tegra_rt5677_dai.codec_of_node); - tegra_rt5677_dai.codec_of_node = NULL; + of_node_put(tegra_rt5677_dai.codecs->of_node); + tegra_rt5677_dai.codecs->of_node = NULL; err: return ret; } @@ -303,11 +308,11 @@ static int tegra_rt5677_remove(struct platform_device *pdev) tegra_asoc_utils_fini(&machine->util_data); - tegra_rt5677_dai.platform_of_node = NULL; - of_node_put(tegra_rt5677_dai.codec_of_node); - tegra_rt5677_dai.codec_of_node = NULL; - of_node_put(tegra_rt5677_dai.cpu_of_node); - tegra_rt5677_dai.cpu_of_node = NULL; + tegra_rt5677_dai.platforms->of_node = NULL; + of_node_put(tegra_rt5677_dai.codecs->of_node); + tegra_rt5677_dai.codecs->of_node = NULL; + of_node_put(tegra_rt5677_dai.cpus->of_node); + tegra_rt5677_dai.cpus->of_node = NULL; return 0; } From efefce542260fb9c26634fa01582aabc72166259 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:36 +0900 Subject: [PATCH 256/626] ASoC: tegra: tegra_wm8753: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8753.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 23a810e3bacc..8492b3dbb788 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -98,14 +98,19 @@ static const struct snd_soc_dapm_widget tegra_wm8753_dapm_widgets[] = { SND_SOC_DAPM_MIC("Mic Jack", NULL), }; +SND_SOC_DAILINK_DEFS(pcm, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8753-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tegra_wm8753_dai = { .name = "WM8753", .stream_name = "WM8753 PCM", - .codec_dai_name = "wm8753-hifi", .ops = &tegra_wm8753_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(pcm), }; static struct snd_soc_card snd_soc_tegra_wm8753 = { @@ -142,25 +147,25 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev) if (ret) goto err; - tegra_wm8753_dai.codec_of_node = of_parse_phandle(np, + tegra_wm8753_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); - if (!tegra_wm8753_dai.codec_of_node) { + if (!tegra_wm8753_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_wm8753_dai.cpu_of_node = of_parse_phandle(np, + tegra_wm8753_dai.cpus->of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_wm8753_dai.cpu_of_node) { + if (!tegra_wm8753_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_wm8753_dai.platform_of_node = tegra_wm8753_dai.cpu_of_node; + tegra_wm8753_dai.platforms->of_node = tegra_wm8753_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) From 706e20515ef6a370afb31ac49f897c2d2459011a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:41 +0900 Subject: [PATCH 257/626] ASoC: tegra: trimslice: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/trimslice.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 99bcdd979eb2..a553daa34e87 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -91,14 +91,19 @@ static const struct snd_soc_dapm_route trimslice_audio_map[] = { {"RLINEIN", NULL, "Line In"}, }; +SND_SOC_DAILINK_DEFS(single_dsp, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { .name = "TLV320AIC23", .stream_name = "AIC23", - .codec_dai_name = "tlv320aic23-hifi", .ops = &trimslice_asoc_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(single_dsp), }; static struct snd_soc_card snd_soc_trimslice = { @@ -129,26 +134,26 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev) card->dev = &pdev->dev; snd_soc_card_set_drvdata(card, trimslice); - trimslice_tlv320aic23_dai.codec_of_node = of_parse_phandle(np, + trimslice_tlv320aic23_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); - if (!trimslice_tlv320aic23_dai.codec_of_node) { + if (!trimslice_tlv320aic23_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); ret = -EINVAL; goto err; } - trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle(np, + trimslice_tlv320aic23_dai.cpus->of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!trimslice_tlv320aic23_dai.cpu_of_node) { + if (!trimslice_tlv320aic23_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err; } - trimslice_tlv320aic23_dai.platform_of_node = - trimslice_tlv320aic23_dai.cpu_of_node; + trimslice_tlv320aic23_dai.platforms->of_node = + trimslice_tlv320aic23_dai.cpus->of_node; ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); if (ret) From af297e6f2c6731373a270537b00956c816a43aa7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:46 +0900 Subject: [PATCH 258/626] ASoC: tegra: tegra_alc5632: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 37 +++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 98d87801d57a..5a63249ae812 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -124,15 +124,20 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(pcm, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "alc5632-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tegra_alc5632_dai = { .name = "ALC5632", .stream_name = "ALC5632 PCM", - .codec_dai_name = "alc5632-hifi", .init = tegra_alc5632_asoc_init, .ops = &tegra_alc5632_asoc_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(pcm), }; static struct snd_soc_card snd_soc_tegra_alc5632 = { @@ -174,26 +179,26 @@ static int tegra_alc5632_probe(struct platform_device *pdev) if (ret) goto err; - tegra_alc5632_dai.codec_of_node = of_parse_phandle( + tegra_alc5632_dai.codecs->of_node = of_parse_phandle( pdev->dev.of_node, "nvidia,audio-codec", 0); - if (!tegra_alc5632_dai.codec_of_node) { + if (!tegra_alc5632_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_alc5632_dai.cpu_of_node = of_parse_phandle(np, + tegra_alc5632_dai.cpus->of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_alc5632_dai.cpu_of_node) { + if (!tegra_alc5632_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err_put_codec_of_node; } - tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_of_node; + tegra_alc5632_dai.platforms->of_node = tegra_alc5632_dai.cpus->of_node; ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev); if (ret) @@ -211,12 +216,12 @@ static int tegra_alc5632_probe(struct platform_device *pdev) err_fini_utils: tegra_asoc_utils_fini(&alc5632->util_data); err_put_cpu_of_node: - of_node_put(tegra_alc5632_dai.cpu_of_node); - tegra_alc5632_dai.cpu_of_node = NULL; - tegra_alc5632_dai.platform_of_node = NULL; + of_node_put(tegra_alc5632_dai.cpus->of_node); + tegra_alc5632_dai.cpus->of_node = NULL; + tegra_alc5632_dai.platforms->of_node = NULL; err_put_codec_of_node: - of_node_put(tegra_alc5632_dai.codec_of_node); - tegra_alc5632_dai.codec_of_node = NULL; + of_node_put(tegra_alc5632_dai.codecs->of_node); + tegra_alc5632_dai.codecs->of_node = NULL; err: return ret; } @@ -230,11 +235,11 @@ static int tegra_alc5632_remove(struct platform_device *pdev) tegra_asoc_utils_fini(&machine->util_data); - of_node_put(tegra_alc5632_dai.cpu_of_node); - tegra_alc5632_dai.cpu_of_node = NULL; - tegra_alc5632_dai.platform_of_node = NULL; - of_node_put(tegra_alc5632_dai.codec_of_node); - tegra_alc5632_dai.codec_of_node = NULL; + of_node_put(tegra_alc5632_dai.cpus->of_node); + tegra_alc5632_dai.cpus->of_node = NULL; + tegra_alc5632_dai.platforms->of_node = NULL; + of_node_put(tegra_alc5632_dai.codecs->of_node); + tegra_alc5632_dai.codecs->of_node = NULL; return 0; } From f4d9dd95f31bef764aaa857dbaa0b3ad2aa98298 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:51 +0900 Subject: [PATCH 259/626] ASoC: tegra: tegra_sgtl5000: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_sgtl5000.c | 37 ++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c index 901457da25ec..c5d45a6147bd 100644 --- a/sound/soc/tegra/tegra_sgtl5000.c +++ b/sound/soc/tegra/tegra_sgtl5000.c @@ -92,13 +92,18 @@ static const struct snd_soc_dapm_widget tegra_sgtl5000_dapm_widgets[] = { SND_SOC_DAPM_MIC("Mic Jack", NULL), }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tegra_sgtl5000_dai = { .name = "sgtl5000", .stream_name = "HiFi", - .codec_dai_name = "sgtl5000", .ops = &tegra_sgtl5000_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card snd_soc_tegra_sgtl5000 = { @@ -134,25 +139,25 @@ static int tegra_sgtl5000_driver_probe(struct platform_device *pdev) if (ret) goto err; - tegra_sgtl5000_dai.codec_of_node = of_parse_phandle(np, + tegra_sgtl5000_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); - if (!tegra_sgtl5000_dai.codec_of_node) { + if (!tegra_sgtl5000_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_sgtl5000_dai.cpu_of_node = of_parse_phandle(np, + tegra_sgtl5000_dai.cpus->of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_sgtl5000_dai.cpu_of_node) { + if (!tegra_sgtl5000_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing/invalid\n"); ret = -EINVAL; goto err_put_codec_of_node; } - tegra_sgtl5000_dai.platform_of_node = tegra_sgtl5000_dai.cpu_of_node; + tegra_sgtl5000_dai.platforms->of_node = tegra_sgtl5000_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) @@ -170,12 +175,12 @@ static int tegra_sgtl5000_driver_probe(struct platform_device *pdev) err_fini_utils: tegra_asoc_utils_fini(&machine->util_data); err_put_cpu_of_node: - of_node_put(tegra_sgtl5000_dai.cpu_of_node); - tegra_sgtl5000_dai.cpu_of_node = NULL; - tegra_sgtl5000_dai.platform_of_node = NULL; + of_node_put(tegra_sgtl5000_dai.cpus->of_node); + tegra_sgtl5000_dai.cpus->of_node = NULL; + tegra_sgtl5000_dai.platforms->of_node = NULL; err_put_codec_of_node: - of_node_put(tegra_sgtl5000_dai.codec_of_node); - tegra_sgtl5000_dai.codec_of_node = NULL; + of_node_put(tegra_sgtl5000_dai.codecs->of_node); + tegra_sgtl5000_dai.codecs->of_node = NULL; err: return ret; } @@ -190,11 +195,11 @@ static int tegra_sgtl5000_driver_remove(struct platform_device *pdev) tegra_asoc_utils_fini(&machine->util_data); - of_node_put(tegra_sgtl5000_dai.cpu_of_node); - tegra_sgtl5000_dai.cpu_of_node = NULL; - tegra_sgtl5000_dai.platform_of_node = NULL; - of_node_put(tegra_sgtl5000_dai.codec_of_node); - tegra_sgtl5000_dai.codec_of_node = NULL; + of_node_put(tegra_sgtl5000_dai.cpus->of_node); + tegra_sgtl5000_dai.cpus->of_node = NULL; + tegra_sgtl5000_dai.platforms->of_node = NULL; + of_node_put(tegra_sgtl5000_dai.codecs->of_node); + tegra_sgtl5000_dai.codecs->of_node = NULL; return ret; } From 5a44ad1e587a3ff8d4d92340543327b4245dc7fa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:18:56 +0900 Subject: [PATCH 260/626] ASoC: tegra: tegra_rt5640: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_rt5640.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index fc81b48aa9d6..3f0756132ac4 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -126,14 +126,19 @@ static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(aif1, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5640-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tegra_rt5640_dai = { .name = "RT5640", .stream_name = "RT5640 PCM", - .codec_dai_name = "rt5640-aif1", .init = tegra_rt5640_asoc_init, .ops = &tegra_rt5640_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(aif1), }; static struct snd_soc_card snd_soc_tegra_rt5640 = { @@ -176,25 +181,25 @@ static int tegra_rt5640_probe(struct platform_device *pdev) if (ret) goto err; - tegra_rt5640_dai.codec_of_node = of_parse_phandle(np, + tegra_rt5640_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); - if (!tegra_rt5640_dai.codec_of_node) { + if (!tegra_rt5640_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_rt5640_dai.cpu_of_node = of_parse_phandle(np, + tegra_rt5640_dai.cpus->of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_rt5640_dai.cpu_of_node) { + if (!tegra_rt5640_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_rt5640_dai.platform_of_node = tegra_rt5640_dai.cpu_of_node; + tegra_rt5640_dai.platforms->of_node = tegra_rt5640_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) From 5e703b906e195bc278d4f88609ea84da8c43cd93 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:01 +0900 Subject: [PATCH 261/626] ASoC: tegra: tegra_wm8903: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 69bc9461974b..5915bf4cf496 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -209,15 +209,20 @@ static int tegra_wm8903_remove(struct snd_soc_card *card) return 0; } +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8903-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tegra_wm8903_dai = { .name = "WM8903", .stream_name = "WM8903 PCM", - .codec_dai_name = "wm8903-hifi", .init = tegra_wm8903_init, .ops = &tegra_wm8903_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card snd_soc_tegra_wm8903 = { @@ -316,25 +321,25 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev) if (ret) goto err; - tegra_wm8903_dai.codec_of_node = of_parse_phandle(np, + tegra_wm8903_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); - if (!tegra_wm8903_dai.codec_of_node) { + if (!tegra_wm8903_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np, + tegra_wm8903_dai.cpus->of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_wm8903_dai.cpu_of_node) { + if (!tegra_wm8903_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_wm8903_dai.platform_of_node = tegra_wm8903_dai.cpu_of_node; + tegra_wm8903_dai.platforms->of_node = tegra_wm8903_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) From ec7687d9a10a40dfc34d2d8f546b63195eebdad3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:05 +0900 Subject: [PATCH 262/626] ASoC: tegra: tegra_wm9712: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm9712.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c index 864a3345972e..7526aee3a0e3 100644 --- a/sound/soc/tegra/tegra_wm9712.c +++ b/sound/soc/tegra/tegra_wm9712.c @@ -49,12 +49,16 @@ static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd) return snd_soc_dapm_force_enable_pin(&rtd->card->dapm, "Mic Bias"); } +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tegra_wm9712_dai = { .name = "AC97 HiFi", .stream_name = "AC97 HiFi", - .codec_dai_name = "wm9712-hifi", - .codec_name = "wm9712-codec", .init = tegra_wm9712_init, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card snd_soc_tegra_wm9712 = { @@ -101,16 +105,16 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev) if (ret) goto codec_unregister; - tegra_wm9712_dai.cpu_of_node = of_parse_phandle(np, + tegra_wm9712_dai.cpus->of_node = of_parse_phandle(np, "nvidia,ac97-controller", 0); - if (!tegra_wm9712_dai.cpu_of_node) { + if (!tegra_wm9712_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,ac97-controller' missing or invalid\n"); ret = -EINVAL; goto codec_unregister; } - tegra_wm9712_dai.platform_of_node = tegra_wm9712_dai.cpu_of_node; + tegra_wm9712_dai.platforms->of_node = tegra_wm9712_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) From f60adf38514183b897301cdf616ef8bf5ef34094 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:10 +0900 Subject: [PATCH 263/626] ASoC: tegra: tegra_max98090: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_max98090.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index cf142e2c7bd7..b6c1f4839266 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c @@ -176,14 +176,19 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEFS(pcm, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link tegra_max98090_dai = { .name = "max98090", .stream_name = "max98090 PCM", - .codec_dai_name = "HiFi", .init = tegra_max98090_asoc_init, .ops = &tegra_max98090_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(pcm), }; static struct snd_soc_card snd_soc_tegra_max98090 = { @@ -230,25 +235,25 @@ static int tegra_max98090_probe(struct platform_device *pdev) if (ret) goto err; - tegra_max98090_dai.codec_of_node = of_parse_phandle(np, + tegra_max98090_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); - if (!tegra_max98090_dai.codec_of_node) { + if (!tegra_max98090_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_max98090_dai.cpu_of_node = of_parse_phandle(np, + tegra_max98090_dai.cpus->of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_max98090_dai.cpu_of_node) { + if (!tegra_max98090_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_max98090_dai.platform_of_node = tegra_max98090_dai.cpu_of_node; + tegra_max98090_dai.platforms->of_node = tegra_max98090_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) From 23b946ce2808bd4f1bfca1bae1fafbf552be18a4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:14 +0900 Subject: [PATCH 264/626] ASoC: soc-topology: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 3299ebb48c1a..f485f7f751a1 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -560,7 +560,7 @@ static void remove_link(struct snd_soc_component *comp, kfree(link->name); kfree(link->stream_name); - kfree(link->cpu_dai_name); + kfree(link->cpus->dai_name); list_del(&dobj->list); snd_soc_remove_dai_link(comp->card, link); @@ -1879,12 +1879,22 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, struct snd_soc_tplg_pcm *pcm) { struct snd_soc_dai_link *link; + struct snd_soc_dai_link_component *dlc; int ret; - link = kzalloc(sizeof(struct snd_soc_dai_link), GFP_KERNEL); + /* link + cpu + codec */ + link = kzalloc(sizeof(*link) + (2 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; + dlc = (struct snd_soc_dai_link_component *)(link + 1); + + link->cpus = &dlc[0]; + link->codecs = &dlc[1]; + + link->num_cpus = 1; + link->num_codecs = 1; + if (strlen(pcm->pcm_name)) { link->name = kstrdup(pcm->pcm_name, GFP_KERNEL); link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL); @@ -1892,10 +1902,10 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->id = le32_to_cpu(pcm->pcm_id); if (strlen(pcm->dai_name)) - link->cpu_dai_name = kstrdup(pcm->dai_name, GFP_KERNEL); + link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL); - link->codec_name = "snd-soc-dummy"; - link->codec_dai_name = "snd-soc-dummy-dai"; + link->codecs->name = "snd-soc-dummy"; + link->codecs->dai_name = "snd-soc-dummy-dai"; /* enable DPCM */ link->dynamic = 1; @@ -1912,7 +1922,7 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n"); kfree(link->name); kfree(link->stream_name); - kfree(link->cpu_dai_name); + kfree(link->cpus->dai_name); kfree(link); return ret; } From 0467d8ef0f61c91774f49a2d287b4d6fe58d5bdb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:19 +0900 Subject: [PATCH 265/626] ASoC: vc4: vc4_htmi: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- drivers/gpu/drm/vc4/vc4_hdmi.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 99fc8569e0f5..6beac1ca1f27 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -69,6 +69,9 @@ struct vc4_hdmi_audio { struct snd_soc_card card; struct snd_soc_dai_link link; + struct snd_soc_dai_link_component cpu; + struct snd_soc_dai_link_component codec; + struct snd_soc_dai_link_component platform; int samplerate; int channels; struct snd_dmaengine_dai_dma_data dma_data; @@ -1096,12 +1099,20 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi) return ret; } + dai_link->cpus = &hdmi->audio.cpu; + dai_link->codecs = &hdmi->audio.codec; + dai_link->platforms = &hdmi->audio.platform; + + dai_link->num_cpus = 1; + dai_link->num_codecs = 1; + dai_link->num_platforms = 1; + dai_link->name = "MAI"; dai_link->stream_name = "MAI PCM"; - dai_link->codec_dai_name = vc4_hdmi_audio_codec_dai_drv.name; - dai_link->cpu_dai_name = dev_name(dev); - dai_link->codec_name = dev_name(dev); - dai_link->platform_name = dev_name(dev); + dai_link->codecs->dai_name = vc4_hdmi_audio_codec_dai_drv.name; + dai_link->cpus->dai_name = dev_name(dev); + dai_link->codecs->name = dev_name(dev); + dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From 7ba06110de2628137554cf4da849ef08f255f385 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:24 +0900 Subject: [PATCH 266/626] ASoC: sof: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sof/nocodec.c | 21 +++++++++++++++++---- sound/soc/sof/topology.c | 20 +++++++++----------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index f84b4344dcc3..3d128e5a132c 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -21,6 +21,7 @@ static int sof_nocodec_bes_setup(struct device *dev, struct snd_soc_dai_link *links, int link_num, struct snd_soc_card *card) { + struct snd_soc_dai_link_component *dlc; int i; if (!ops || !links || !card) @@ -28,17 +29,29 @@ static int sof_nocodec_bes_setup(struct device *dev, /* set up BE dai_links */ for (i = 0; i < link_num; i++) { + dlc = devm_kzalloc(dev, 3 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return -ENOMEM; + links[i].name = devm_kasprintf(dev, GFP_KERNEL, "NoCodec-%d", i); if (!links[i].name) return -ENOMEM; + links[i].cpus = &dlc[0]; + links[i].codecs = &dlc[1]; + links[i].platforms = &dlc[2]; + + links[i].num_cpus = 1; + links[i].num_codecs = 1; + links[i].num_platforms = 1; + links[i].id = i; links[i].no_pcm = 1; - links[i].cpu_dai_name = ops->drv[i].name; - links[i].platform_name = dev_name(dev); - links[i].codec_dai_name = "snd-soc-dummy-dai"; - links[i].codec_name = "snd-soc-dummy"; + links[i].cpus->dai_name = ops->drv[i].name; + links[i].platforms->name = dev_name(dev); + links[i].codecs->dai_name = "snd-soc-dummy-dai"; + links[i].codecs->name = "snd-soc-dummy"; links[i].dpcm_playback = 1; links[i].dpcm_capture = 1; } diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index b969686f954f..a13233ae6d0e 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2639,7 +2639,6 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, struct sof_ipc_dai_config *config) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct snd_soc_dai_link_component dai_component; struct snd_soc_tplg_private *private = &cfg->priv; struct snd_soc_dai *dai; u32 size = sizeof(*config); @@ -2650,7 +2649,6 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, int ret; /* init IPC */ - memset(&dai_component, 0, sizeof(dai_component)); memset(&config->hda, 0, sizeof(struct sof_ipc_dai_hda_params)); config->hdr.size = size; @@ -2664,11 +2662,10 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, return ret; } - dai_component.dai_name = link->cpu_dai_name; - dai = snd_soc_find_dai(&dai_component); + dai = snd_soc_find_dai(link->cpus); if (!dai) { dev_err(sdev->dev, "error: failed to find dai %s in %s", - dai_component.dai_name, __func__); + link->cpus->dai_name, __func__); return -EINVAL; } @@ -2708,7 +2705,11 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, int ret; int i = 0; - link->platform_name = dev_name(sdev->dev); + if (!link->platforms) { + dev_err(sdev->dev, "error: no platforms\n"); + return -EINVAL; + } + link->platforms->name = dev_name(sdev->dev); /* * Set nonatomic property for FE dai links as their trigger action @@ -2801,16 +2802,13 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, static int sof_link_hda_unload(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link) { - struct snd_soc_dai_link_component dai_component; struct snd_soc_dai *dai; int ret = 0; - memset(&dai_component, 0, sizeof(dai_component)); - dai_component.dai_name = link->cpu_dai_name; - dai = snd_soc_find_dai(&dai_component); + dai = snd_soc_find_dai(link->cpus); if (!dai) { dev_err(sdev->dev, "error: failed to find dai %s in %s", - dai_component.dai_name, __func__); + link->cpus->dai_name, __func__); return -EINVAL; } From 3f6c2a2e9abe1ac636a49ad96dfbb42ce8d39be9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:30 +0900 Subject: [PATCH 267/626] ASoC: Intel: bdw-rt5677: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/bdw-rt5677.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 6520a8ea5537..ff32be5af019 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -257,16 +257,24 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) } /* broadwell digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(fe, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("haswell-pcm-audio"))); + +SND_SOC_DAILINK_DEF(be, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RT5677CE:00", "rt5677-aif1"))); + static struct snd_soc_dai_link bdw_rt5677_dais[] = { /* Front End DAI links */ { .name = "System PCM", .stream_name = "System Playback/Capture", - .cpu_dai_name = "System Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", #if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) .init = bdw_rt5677_rtd_init, #endif @@ -276,6 +284,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { }, .dpcm_capture = 1, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(fe, dummy, platform), }, /* Back End DAI links */ @@ -283,11 +292,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { /* SSP0 - Codec */ .name = "Codec", .id = 0, - .cpu_dai_name = "snd-soc-dummy-dai", - .platform_name = "snd-soc-dummy", .no_pcm = 1, - .codec_name = "i2c-RT5677CE:00", - .codec_dai_name = "rt5677-aif1", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, @@ -297,6 +302,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = bdw_rt5677_init, + SND_SOC_DAILINK_REG(dummy, be, dummy), }, }; From 77b365b8e99d0ddb6a62fe3e93ebbbe14a2734ab Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:35 +0900 Subject: [PATCH 268/626] ASoC: Intel: haswell: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/haswell.c | 46 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 971226d42042..aace44e09fc2 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -105,53 +105,62 @@ static int haswell_rtd_init(struct snd_soc_pcm_runtime *rtd) return 0; } +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(offload0, + DAILINK_COMP_ARRAY(COMP_CPU("Offload0 Pin"))); + +SND_SOC_DAILINK_DEF(offload1, + DAILINK_COMP_ARRAY(COMP_CPU("Offload1 Pin"))); + +SND_SOC_DAILINK_DEF(loopback, + DAILINK_COMP_ARRAY(COMP_CPU("Loopback Pin"))); + +SND_SOC_DAILINK_DEF(codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT33CA:00", "rt5640-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("haswell-pcm-audio"))); + static struct snd_soc_dai_link haswell_rt5640_dais[] = { /* Front End DAI links */ { .name = "System", .stream_name = "System Playback/Capture", - .cpu_dai_name = "System Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .init = haswell_rtd_init, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(system, dummy, platform), }, { .name = "Offload0", .stream_name = "Offload0 Playback", - .cpu_dai_name = "Offload0 Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(offload0, dummy, platform), }, { .name = "Offload1", .stream_name = "Offload1 Playback", - .cpu_dai_name = "Offload1 Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(offload1, dummy, platform), }, { .name = "Loopback", .stream_name = "Loopback", - .cpu_dai_name = "Loopback Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(loopback, dummy, platform), }, /* Back End DAI links */ @@ -159,11 +168,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { /* SSP0 - Codec */ .name = "Codec", .id = 0, - .cpu_dai_name = "snd-soc-dummy-dai", - .platform_name = "snd-soc-dummy", .no_pcm = 1, - .codec_name = "i2c-INT33CA:00", - .codec_dai_name = "rt5640-aif1", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, @@ -172,6 +177,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { .ops = &haswell_rt5640_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(dummy, codec, dummy), }, }; From 4c3db473f77ddb8a632c4b66a35ae1855de3a1b7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:19:40 +0900 Subject: [PATCH 269/626] ASoC: Intel: broadwell: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/broadwell.c | 46 +++++++++++++++++------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 0f18f8964f51..fd8d88550d0b 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -152,67 +152,72 @@ static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) } #endif +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(offload0, + DAILINK_COMP_ARRAY(COMP_CPU("Offload0 Pin"))); + +SND_SOC_DAILINK_DEF(offload1, + DAILINK_COMP_ARRAY(COMP_CPU("Offload1 Pin"))); + +SND_SOC_DAILINK_DEF(loopback, + DAILINK_COMP_ARRAY(COMP_CPU("Loopback Pin"))); + +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("haswell-pcm-audio"))); + +SND_SOC_DAILINK_DEF(codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00", "rt286-aif1"))); + /* broadwell digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link broadwell_rt286_dais[] = { /* Front End DAI links */ { .name = "System PCM", .stream_name = "System Playback/Capture", - .cpu_dai_name = "System Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", #if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) .init = broadwell_rtd_init, #endif .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(system, dummy, platform), }, { .name = "Offload0", .stream_name = "Offload0 Playback", - .cpu_dai_name = "Offload0 Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(offload0, dummy, platform), }, { .name = "Offload1", .stream_name = "Offload1 Playback", - .cpu_dai_name = "Offload1 Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(offload1, dummy, platform), }, { .name = "Loopback PCM", .stream_name = "Loopback", - .cpu_dai_name = "Loopback Pin", - .platform_name = "haswell-pcm-audio", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(loopback, dummy, platform), }, /* Back End DAI links */ { /* SSP0 - Codec */ .name = "Codec", .id = 0, - .cpu_dai_name = "snd-soc-dummy-dai", - .platform_name = "snd-soc-dummy", .no_pcm = 1, - .codec_name = "i2c-INT343A:00", - .codec_dai_name = "rt286-aif1", .init = broadwell_rt286_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -222,6 +227,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { .ops = &broadwell_rt286_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(dummy, codec, dummy), }, }; From 56b2f3187419b1fed17d4d1cb051ffdce2fcbbcb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:00 +0900 Subject: [PATCH 270/626] ASoC: Intel: bxt_da7219_max98357a: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/bxt_da7219_max98357a.c | 140 ++++++++++-------- 1 file changed, 80 insertions(+), 60 deletions(-) diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 4ee769a86201..d712623854a3 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -373,146 +373,177 @@ static const struct snd_soc_ops broxton_refcap_ops = { }; /* broxton digital audio interface glue - connects codec <--> CPU */ +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(system2, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); + +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + + /* Back End DAI */ +SND_SOC_DAILINK_DEF(ssp5_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin"))); +SND_SOC_DAILINK_DEF(ssp5_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", + BXT_MAXIM_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(ssp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); +SND_SOC_DAILINK_DEF(ssp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", + BXT_DIALOG_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(dmic_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", + "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", + "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0"))); + static struct snd_soc_dai_link broxton_dais[] = { /* Front End DAI links */ [BXT_DPCM_AUDIO_PB] = { .name = "Bxt Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:0e.0", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = broxton_da7219_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &broxton_da7219_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [BXT_DPCM_AUDIO_CP] = { .name = "Bxt Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:0e.0", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &broxton_da7219_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [BXT_DPCM_AUDIO_HS_PB] = { .name = "Bxt Audio Headset Playback", .stream_name = "Headset Playback", - .cpu_dai_name = "System Pin2", - .platform_name = "0000:00:0e.0", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &broxton_da7219_fe_ops, + SND_SOC_DAILINK_REG(system2, dummy, platform), }, [BXT_DPCM_AUDIO_REF_CP] = { .name = "Bxt Audio Reference cap", .stream_name = "Refcap", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &broxton_refcap_ops, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [BXT_DPCM_AUDIO_DMIC_CP] = { .name = "Bxt Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &broxton_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [BXT_DPCM_AUDIO_HDMI1_PB] = { .name = "Bxt HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [BXT_DPCM_AUDIO_HDMI2_PB] = { .name = "Bxt HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [BXT_DPCM_AUDIO_HDMI3_PB] = { .name = "Bxt HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ { /* SSP5 - Codec */ .name = "SSP5-Codec", .id = 0, - .cpu_dai_name = "SSP5 Pin", - .platform_name = "0000:00:0e.0", .no_pcm = 1, - .codec_name = "MX98357A:00", - .codec_dai_name = BXT_MAXIM_CODEC_DAI, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_pmdown_time = 1, .be_hw_params_fixup = broxton_ssp_fixup, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), }, { /* SSP1 - Codec */ .name = "SSP1-Codec", .id = 1, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:0e.0", .no_pcm = 1, - .codec_name = "i2c-DLGS7219:00", - .codec_dai_name = BXT_DIALOG_CODEC_DAI, .init = broxton_da7219_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -520,51 +551,40 @@ static struct snd_soc_dai_link broxton_dais[] = { .be_hw_params_fixup = broxton_ssp_fixup, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "dmic01", .id = 2, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:0e.0", .ignore_suspend = 1, .be_hw_params_fixup = broxton_dmic_fixup, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:0e.0", .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:0e.0", .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 5, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:0e.0", .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; @@ -647,16 +667,16 @@ static int broxton_audio_probe(struct platform_device *pdev) /* Fixup the SSP entries for geminilake */ for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { /* MAXIM_CODEC is connected to SSP1. */ - if (!strcmp(broxton_dais[i].codec_dai_name, + if (!strcmp(broxton_dais[i].codecs->dai_name, BXT_MAXIM_CODEC_DAI)) { broxton_dais[i].name = "SSP1-Codec"; - broxton_dais[i].cpu_dai_name = "SSP1 Pin"; + broxton_dais[i].cpus->dai_name = "SSP1 Pin"; } /* DIALOG_CODE is connected to SSP2 */ - else if (!strcmp(broxton_dais[i].codec_dai_name, + else if (!strcmp(broxton_dais[i].codecs->dai_name, BXT_DIALOG_CODEC_DAI)) { broxton_dais[i].name = "SSP2-Codec"; - broxton_dais[i].cpu_dai_name = "SSP2 Pin"; + broxton_dais[i].cpus->dai_name = "SSP2 Pin"; } } } From 5895eb75edf0f49274b8898c62c9013de5ba68fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:05 +0900 Subject: [PATCH 271/626] ASoC: Intel: bxt_rt298: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/bxt_rt298.c | 135 ++++++++++++++++------------- 1 file changed, 77 insertions(+), 58 deletions(-) diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index e91057f83d20..e3bf5aaf4925 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -331,6 +331,64 @@ static const struct snd_soc_ops broxton_rt286_fe_ops = { .startup = bxt_fe_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(ssp5_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin"))); +SND_SOC_DAILINK_DEF(ssp5_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00", + "rt298-aif1"))); + +SND_SOC_DAILINK_DEF(dmic_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); + +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", + "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(dmic16k, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", + "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", + "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", + "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0"))); + /* broxton digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link broxton_rt298_dais[] = { /* Front End DAI links */ @@ -338,107 +396,82 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { { .name = "Bxt Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:0e.0", .nonatomic = 1, .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .init = broxton_rt298_fe_init, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &broxton_rt286_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [BXT_DPCM_AUDIO_CP] = { .name = "Bxt Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:0e.0", .nonatomic = 1, .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &broxton_rt286_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [BXT_DPCM_AUDIO_REF_CP] = { .name = "Bxt Audio Reference cap", .stream_name = "refcap", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [BXT_DPCM_AUDIO_DMIC_CP] = { .name = "Bxt Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &broxton_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [BXT_DPCM_AUDIO_HDMI1_PB] = { .name = "Bxt HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [BXT_DPCM_AUDIO_HDMI2_PB] = { .name = "Bxt HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [BXT_DPCM_AUDIO_HDMI3_PB] = { .name = "Bxt HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ { /* SSP5 - Codec */ .name = "SSP5-Codec", .id = 0, - .cpu_dai_name = "SSP5 Pin", - .platform_name = "0000:00:0e.0", .no_pcm = 1, - .codec_name = "i2c-INT343A:00", - .codec_dai_name = "rt298-aif1", .init = broxton_rt298_codec_init, .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -447,63 +480,49 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .ops = &broxton_rt298_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), }, { .name = "dmic01", .id = 1, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:0e.0", .be_hw_params_fixup = broxton_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "dmic16k", .id = 2, - .cpu_dai_name = "DMIC16k Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:0e.0", .be_hw_params_fixup = broxton_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:0e.0", .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:0e.0", .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 5, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:0e.0", .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; @@ -583,16 +602,16 @@ static int broxton_audio_probe(struct platform_device *pdev) int i; for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) { - if (!strncmp(card->dai_link[i].codec_name, "i2c-INT343A:00", - I2C_NAME_SIZE)) { + if (!strncmp(card->dai_link[i].codecs->name, "i2c-INT343A:00", + I2C_NAME_SIZE)) { if (!strncmp(card->name, "broxton-rt298", - PLATFORM_NAME_SIZE)) { + PLATFORM_NAME_SIZE)) { card->dai_link[i].name = "SSP5-Codec"; - card->dai_link[i].cpu_dai_name = "SSP5 Pin"; + card->dai_link[i].cpus->dai_name = "SSP5 Pin"; } else if (!strncmp(card->name, "geminilake-rt298", - PLATFORM_NAME_SIZE)) { + PLATFORM_NAME_SIZE)) { card->dai_link[i].name = "SSP2-Codec"; - card->dai_link[i].cpu_dai_name = "SSP2 Pin"; + card->dai_link[i].cpus->dai_name = "SSP2 Pin"; } } } From 6bf449c4c49a90ea973fb9b17418a79c53598b11 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:10 +0900 Subject: [PATCH 272/626] ASoC: Intel: byt-rt5640: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/byt-rt5640.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/byt-rt5640.c b/sound/soc/intel/boards/byt-rt5640.c index df902d82145e..483043f1650f 100644 --- a/sound/soc/intel/boards/byt-rt5640.c +++ b/sound/soc/intel/boards/byt-rt5640.c @@ -180,18 +180,20 @@ static struct snd_soc_ops byt_rt5640_ops = { .hw_params = byt_rt5640_hw_params, }; +SND_SOC_DAILINK_DEFS(audio, + DAILINK_COMP_ARRAY(COMP_CPU("baytrail-pcm-audio")), + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5640:00", "rt5640-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("baytrail-pcm-audio"))); + static struct snd_soc_dai_link byt_rt5640_dais[] = { { .name = "Baytrail Audio", .stream_name = "Audio", - .cpu_dai_name = "baytrail-pcm-audio", - .codec_dai_name = "rt5640-aif1", - .codec_name = "i2c-10EC5640:00", - .platform_name = "baytrail-pcm-audio", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .init = byt_rt5640_init, .ops = &byt_rt5640_ops, + SND_SOC_DAILINK_REG(audio), }, }; From 0034172031aa695911cc2c2db2a3cd76ebff6cf4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:15 +0900 Subject: [PATCH 273/626] ASoC: Intel: byt-max98090: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/byt-max98090.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/byt-max98090.c b/sound/soc/intel/boards/byt-max98090.c index f1283634b22b..589499fcd36d 100644 --- a/sound/soc/intel/boards/byt-max98090.c +++ b/sound/soc/intel/boards/byt-max98090.c @@ -117,17 +117,19 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) hs_jack_gpios); } +SND_SOC_DAILINK_DEFS(baytrail, + DAILINK_COMP_ARRAY(COMP_CPU("baytrail-pcm-audio")), + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-193C9890:00", "HiFi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("baytrail-pcm-audio"))); + static struct snd_soc_dai_link byt_max98090_dais[] = { { .name = "Baytrail Audio", .stream_name = "Audio", - .cpu_dai_name = "baytrail-pcm-audio", - .codec_dai_name = "HiFi", - .codec_name = "i2c-193C9890:00", - .platform_name = "baytrail-pcm-audio", .init = byt_max98090_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(baytrail), }, }; From 143029dbb8c9800bbcd4f74d91769590fafeca52 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:20 +0900 Subject: [PATCH 274/626] ASoC: Intel: bytcht_es8316: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_es8316.c | 38 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 1f319b2a835f..b56f9230d1bc 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -307,32 +307,43 @@ static const struct snd_soc_ops byt_cht_es8316_aif1_ops = { .startup = byt_cht_es8316_aif1_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8316:00", "ES8316 HiFi"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link byt_cht_es8316_dais[] = { [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &byt_cht_es8316_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &byt_cht_es8316_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* back ends */ @@ -342,11 +353,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { */ .name = "SSP2-Codec", .id = 0, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "ES8316 HiFi", - .codec_name = "i2c-ESSX8316:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .be_hw_params_fixup = byt_cht_es8316_codec_fixup, @@ -354,6 +361,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = byt_cht_es8316_init, + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, }; @@ -471,7 +479,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) mach = dev->platform_data; /* fix index of codec dai */ for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) { - if (!strcmp(byt_cht_es8316_dais[i].codec_name, + if (!strcmp(byt_cht_es8316_dais[i].codecs->name, "i2c-ESSX8316:00")) { dai_index = i; break; @@ -484,7 +492,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) snprintf(codec_name, sizeof(codec_name), "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); - byt_cht_es8316_dais[dai_index].codec_name = codec_name; + byt_cht_es8316_dais[dai_index].codecs->name = codec_name; } /* override plaform name, if required */ @@ -518,7 +526,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) log_quirks(dev); if (quirk & BYT_CHT_ES8316_SSP0) - byt_cht_es8316_dais[dai_index].cpu_dai_name = "ssp0-port"; + byt_cht_es8316_dais[dai_index].cpus->dai_name = "ssp0-port"; /* get the clock */ priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3"); From 365a8a586afb7ee4e6736ab7b5020502e121e69d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:25 +0900 Subject: [PATCH 275/626] ASoC: Intel: bytcht_nocodec: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_nocodec.c | 30 +++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/boards/bytcht_nocodec.c b/sound/soc/intel/boards/bytcht_nocodec.c index b80ec027a0e8..ecb8585900bd 100644 --- a/sound/soc/intel/boards/bytcht_nocodec.c +++ b/sound/soc/intel/boards/bytcht_nocodec.c @@ -105,44 +105,49 @@ static struct snd_soc_ops aif1_ops = { .startup = aif1_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link dais[] = { [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .ignore_suspend = 1, .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .ignore_suspend = 1, .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* CODEC<->CODEC link */ /* back ends */ { .name = "SSP2-LowSpeed Connector", .id = 0, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .be_hw_params_fixup = codec_fixup, @@ -150,6 +155,7 @@ static struct snd_soc_dai_link dais[] = { .nonatomic = true, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp2_port, dummy, platform), }, }; From fb1d4861f28e750739f73a59067ea18cadbc56c3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:30 +0900 Subject: [PATCH 276/626] ASoC: Intel: bytcht_da7213: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_da7213.c | 37 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index 9091ee697fbe..7fa2fa0ded6e 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -158,42 +158,50 @@ static const struct snd_soc_ops ssp2_ops = { }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7213:00", + "da7213-hifi"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link dailink[] = { [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* CODEC<->CODEC link */ /* back ends */ { .name = "SSP2-Codec", .id = 0, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "da7213-hifi", - .codec_name = "i2c-DLGS7213:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .be_hw_params_fixup = codec_fixup, @@ -201,6 +209,7 @@ static struct snd_soc_dai_link dailink[] = { .dpcm_playback = 1, .dpcm_capture = 1, .ops = &ssp2_ops, + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, }; @@ -236,7 +245,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev) /* fix index of codec dai */ for (i = 0; i < ARRAY_SIZE(dailink); i++) { - if (!strcmp(dailink[i].codec_name, "i2c-DLGS7213:00")) { + if (!strcmp(dailink[i].codecs->name, "i2c-DLGS7213:00")) { dai_index = i; break; } @@ -248,7 +257,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev) snprintf(codec_name, sizeof(codec_name), "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); - dailink[dai_index].codec_name = codec_name; + dailink[dai_index].codecs->name = codec_name; } /* override plaform name, if required */ From 196c52e13eb5ce1c53d6c3a38227b5ca3032d496 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:34 +0900 Subject: [PATCH 277/626] ASoC: Intel: bytcht_cx2072x: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_cx2072x.c | 37 +++++++++++++++---------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 4b985b393dae..54ac2fd41925 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -150,41 +150,49 @@ static struct snd_soc_ops byt_cht_cx2072x_aif1_ops = { .startup = byt_cht_cx2072x_aif1_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); + +SND_SOC_DAILINK_DEF(cx2072x, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-14F10720:00", "cx2072x-hifi"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = { [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &byt_cht_cx2072x_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &byt_cht_cx2072x_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* back ends */ { .name = "SSP2-Codec", .id = 0, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "cx2072x-hifi", - .codec_name = "i2c-14F10720:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .init = byt_cht_cx2072x_init, @@ -192,6 +200,7 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = { .nonatomic = true, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp2, cx2072x, platform), }, }; @@ -223,7 +232,7 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev) /* fix index of codec dai */ for (i = 0; i < ARRAY_SIZE(byt_cht_cx2072x_dais); i++) { - if (!strcmp(byt_cht_cx2072x_dais[i].codec_name, + if (!strcmp(byt_cht_cx2072x_dais[i].codecs->name, "i2c-14F10720:00")) { dai_index = i; break; @@ -236,7 +245,7 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev) snprintf(codec_name, sizeof(codec_name), "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); - byt_cht_cx2072x_dais[dai_index].codec_name = codec_name; + byt_cht_cx2072x_dais[dai_index].codecs->name = codec_name; } /* override plaform name, if required */ From 01fee62a27c1c66ce916d09e74aaf4eab071096f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:39 +0900 Subject: [PATCH 278/626] ASoC: Intel: bytcr_rt5651: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5651.c | 41 ++++++++++++++++----------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 6df6435ea394..556c44fe893b 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -745,42 +745,49 @@ static const struct snd_soc_ops byt_rt5651_be_ssp2_ops = { .hw_params = byt_rt5651_aif1_hw_params, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5651:00", "rt5651-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link byt_rt5651_dais[] = { [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &byt_rt5651_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &byt_rt5651_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* CODEC<->CODEC link */ /* back ends */ { .name = "SSP2-Codec", .id = 0, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "rt5651-aif1", - .codec_name = "i2c-10EC5651:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .be_hw_params_fixup = byt_rt5651_codec_fixup, @@ -790,6 +797,7 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { .dpcm_capture = 1, .init = byt_rt5651_init, .ops = &byt_rt5651_be_ssp2_ops, + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, }; @@ -894,7 +902,8 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) /* fix index of codec dai */ for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) { - if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) { + if (!strcmp(byt_rt5651_dais[i].codecs->name, + "i2c-10EC5651:00")) { dai_index = i; break; } @@ -906,7 +915,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name), "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); - byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name; + byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name; } else { dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); return -ENODEV; @@ -1046,7 +1055,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) sizeof(byt_rt5651_codec_aif_name), "%s", "rt5651-aif2"); - byt_rt5651_dais[dai_index].codec_dai_name = + byt_rt5651_dais[dai_index].codecs->dai_name = byt_rt5651_codec_aif_name; } @@ -1057,7 +1066,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) sizeof(byt_rt5651_cpu_dai_name), "%s", "ssp0-port"); - byt_rt5651_dais[dai_index].cpu_dai_name = + byt_rt5651_dais[dai_index].cpus->dai_name = byt_rt5651_cpu_dai_name; } From e7a712889b299ea4a28c58605baa827396ce973e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:44 +0900 Subject: [PATCH 279/626] ASoC: Intel: bytcr_rt5640: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 44 +++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 7aae7b78efba..bd747495ef3c 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1026,41 +1026,51 @@ static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = { .hw_params = byt_rt5640_aif1_hw_params, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + /* overwritten for ssp0 routing */ + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC( + /* overwritten with HID */ "i2c-10EC5640:00", + /* changed w/ quirk */ "rt5640-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link byt_rt5640_dais[] = { [MERR_DPCM_AUDIO] = { .name = "Baytrail Audio Port", .stream_name = "Baytrail Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &byt_rt5640_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &byt_rt5640_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* back ends */ { .name = "SSP2-Codec", .id = 0, - .cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */ - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */ - .codec_name = "i2c-10EC5640:00", /* overwritten with HID */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .be_hw_params_fixup = byt_rt5640_codec_fixup, @@ -1070,6 +1080,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .dpcm_capture = 1, .init = byt_rt5640_init, .ops = &byt_rt5640_be_ssp2_ops, + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, }; @@ -1159,7 +1170,8 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) /* fix index of codec dai */ for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { - if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) { + if (!strcmp(byt_rt5640_dais[i].codecs->name, + "i2c-10EC5640:00")) { dai_index = i; break; } @@ -1171,7 +1183,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name), "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); - byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name; + byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name; } /* @@ -1263,7 +1275,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) sizeof(byt_rt5640_codec_aif_name), "%s", "rt5640-aif2"); - byt_rt5640_dais[dai_index].codec_dai_name = + byt_rt5640_dais[dai_index].codecs->dai_name = byt_rt5640_codec_aif_name; } @@ -1275,7 +1287,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) sizeof(byt_rt5640_cpu_dai_name), "%s", "ssp0-port"); - byt_rt5640_dais[dai_index].cpu_dai_name = + byt_rt5640_dais[dai_index].cpus->dai_name = byt_rt5640_cpu_dai_name; } From 75909d7e2e264f848cf112f7ccb15f9254e1e7af Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:48 +0900 Subject: [PATCH 280/626] ASoC: Intel: cht_bsw_rt5645: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_rt5645.c | 43 +++++++++++++++---------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index de5fe58ae3b4..daac92e48703 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -425,48 +425,56 @@ static const struct snd_soc_ops cht_be_ssp2_ops = { .hw_params = cht_aif1_hw_params, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5645:00", "rt5645-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link cht_dailink[] = { [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &cht_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &cht_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* CODEC<->CODEC link */ /* back ends */ { .name = "SSP2-Codec", .id = 0, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "rt5645-aif1", - .codec_name = "i2c-10EC5645:00", .init = cht_codec_init, .be_hw_params_fixup = cht_codec_fixup, .nonatomic = true, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &cht_be_ssp2_ops, + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, }; @@ -555,8 +563,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev) /* set correct codec name */ for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) - if (!strcmp(card->dai_link[i].codec_name, "i2c-10EC5645:00")) { - card->dai_link[i].codec_name = drv->codec_name; + if (!strcmp(card->dai_link[i].codecs->name, + "i2c-10EC5645:00")) { + card->dai_link[i].codecs->name = drv->codec_name; dai_index = i; } @@ -566,7 +575,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name), "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); - cht_dailink[dai_index].codec_name = cht_rt5645_codec_name; + cht_dailink[dai_index].codecs->name = cht_rt5645_codec_name; } /* @@ -637,7 +646,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) sizeof(cht_rt5645_codec_aif_name), "%s", "rt5645-aif2"); - cht_dailink[dai_index].codec_dai_name = + cht_dailink[dai_index].codecs->dai_name = cht_rt5645_codec_aif_name; } @@ -649,7 +658,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) sizeof(cht_rt5645_cpu_dai_name), "%s", "ssp0-port"); - cht_dailink[dai_index].cpu_dai_name = + cht_dailink[dai_index].cpus->dai_name = cht_rt5645_cpu_dai_name; } From 099cc65855598efc1f9fe1f33d00cccface5d568 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:20:54 +0900 Subject: [PATCH 281/626] ASoC: Intel: cht_bsw_max98090_ti: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 32 ++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index c0e0844f75b9..fb775ed7f0b8 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -337,41 +337,48 @@ static struct snd_soc_aux_dev cht_max98090_headset_dev = { .codec_name = "i2c-104C227E:00", }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-193C9890:00", "HiFi"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link cht_dailink[] = { [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &cht_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &cht_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* back ends */ { .name = "SSP2-Codec", .id = 0, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "HiFi", - .codec_name = "i2c-193C9890:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .init = cht_codec_init, @@ -379,6 +386,7 @@ static struct snd_soc_dai_link cht_dailink[] = { .dpcm_playback = 1, .dpcm_capture = 1, .ops = &cht_be_ssp2_ops, + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, }; From a61142bb0aa04ccc26409d91ad9060fbe2f1b926 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:01 +0900 Subject: [PATCH 282/626] ASoC: Intel: cht_bsw_rt5672: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_rt5672.c | 39 +++++++++++++++---------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 0f7770822388..270d5705c542 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -295,32 +295,44 @@ static const struct snd_soc_ops cht_be_ssp2_ops = { .hw_params = cht_aif1_hw_params, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5670:00", + "rt5670-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link cht_dailink[] = { /* Front End DAI links */ [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &cht_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &cht_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, /* Back End DAI links */ @@ -328,17 +340,14 @@ static struct snd_soc_dai_link cht_dailink[] = { /* SSP2 - Codec */ .name = "SSP2-Codec", .id = 0, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, .nonatomic = true, - .codec_dai_name = "rt5670-aif1", - .codec_name = "i2c-10EC5670:00", .init = cht_codec_init, .be_hw_params_fixup = cht_codec_fixup, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &cht_be_ssp2_ops, + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, }; @@ -417,9 +426,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev) "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { - if (!strcmp(cht_dailink[i].codec_name, - RT5672_I2C_DEFAULT)) { - cht_dailink[i].codec_name = drv->codec_name; + if (!strcmp(cht_dailink[i].codecs->name, + RT5672_I2C_DEFAULT)) { + cht_dailink[i].codecs->name = drv->codec_name; break; } } From 5ae4641f5a2b2d83adfb51988961ab76f94fd51e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:07 +0900 Subject: [PATCH 283/626] ASoC: Intel: cht_bsw_nau8824: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_nau8824.c | 41 +++++++++++++++--------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index 02c2fa239331..5165e5d13a8a 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -175,51 +175,59 @@ static const struct snd_soc_ops cht_be_ssp2_ops = { .hw_params = cht_aif1_hw_params, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(compress, + DAILINK_COMP_ARRAY(COMP_CPU("compress-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp2_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508824:00", + NAU8824_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + static struct snd_soc_dai_link cht_dailink[] = { /* Front End DAI links */ [MERR_DPCM_AUDIO] = { .name = "Audio Port", .stream_name = "Audio", - .cpu_dai_name = "media-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, .ops = &cht_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), }, [MERR_DPCM_DEEP_BUFFER] = { .name = "Deep-Buffer Audio Port", .stream_name = "Deep-Buffer Audio", - .cpu_dai_name = "deepbuffer-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .ops = &cht_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, [MERR_DPCM_COMPR] = { .name = "Compressed Port", .stream_name = "Compress", - .cpu_dai_name = "compress-cpu-dai", - .codec_dai_name = "snd-soc-dummy-dai", - .codec_name = "snd-soc-dummy", - .platform_name = "sst-mfld-platform", + SND_SOC_DAILINK_REG(compress, dummy, platform), }, /* Back End DAI links */ { /* SSP2 - Codec */ .name = "SSP2-Codec", .id = 1, - .cpu_dai_name = "ssp2-port", - .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = NAU8824_CODEC_DAI, - .codec_name = "i2c-10508824:00", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS, .init = cht_codec_init, @@ -227,6 +235,7 @@ static struct snd_soc_dai_link cht_dailink[] = { .dpcm_playback = 1, .dpcm_capture = 1, .ops = &cht_be_ssp2_ops, + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, }; From 168bfa962ed22b0fa44ea0d6cf1875cb917a5270 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:12 +0900 Subject: [PATCH 284/626] ASoC: Intel: kbl_rt5660: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5660.c | 83 ++++++++++++++++------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c index 3255e0029276..74fe1f3a5479 100644 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ b/sound/soc/intel/boards/kbl_rt5660.c @@ -317,78 +317,101 @@ static const struct snd_soc_ops kabylake_rt5660_fe_ops = { .startup = kbl_fe_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC3277:00", KBL_RT5660_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* kabylake digital audio interface glue - connects rt5660 codec <--> CPU */ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { /* Front End DAI links */ [KBL_DPCM_AUDIO_PB] = { .name = "Kbl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &kabylake_rt5660_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_CP] = { .name = "Kbl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &kabylake_rt5660_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI3_PB] = { .name = "Kbl HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ @@ -396,11 +419,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "i2c-10EC3277:00", - .codec_dai_name = KBL_RT5660_CODEC_DAI, .init = kabylake_rt5660_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | @@ -410,39 +429,31 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .ops = &kabylake_rt5660_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { .name = "iDisp1", .id = 1, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 2, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 3, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi3_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; From 00c3cfb041a44f2d2f53492af9badbe7e409bed8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:17 +0900 Subject: [PATCH 285/626] ASoC: Intel: kbl_rt5663_max98927: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 184 +++++++++---------- 1 file changed, 85 insertions(+), 99 deletions(-) diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index d71475200b08..2ddbf585af93 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -246,17 +246,6 @@ static struct snd_soc_codec_conf max98927_codec_conf[] = { }, }; -static struct snd_soc_dai_link_component max98927_codec_components[] = { - { /* Left */ - .name = MAXIM_DEV0_NAME, - .dai_name = KBL_MAXIM_CODEC_DAI, - }, - { /* Right */ - .name = MAXIM_DEV1_NAME, - .dai_name = KBL_MAXIM_CODEC_DAI, - }, -}; - static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) { int ret; @@ -590,127 +579,163 @@ static struct snd_soc_ops skylake_refcap_ops = { .startup = kabylake_refcap_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(system2, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); + +SND_SOC_DAILINK_DEF(echoref, + DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin"))); + +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY( + /* Left */ COMP_CODEC(MAXIM_DEV0_NAME, KBL_MAXIM_CODEC_DAI), + /* Right */ COMP_CODEC(MAXIM_DEV1_NAME, KBL_MAXIM_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(ssp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); +SND_SOC_DAILINK_DEF(ssp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5663:00", + KBL_REALTEK_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(dmic01_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* kabylake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link kabylake_dais[] = { /* Front End DAI links */ [KBL_DPCM_AUDIO_PB] = { .name = "Kbl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = kabylake_rt5663_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &kabylake_rt5663_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_CP] = { .name = "Kbl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &kabylake_rt5663_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_HS_PB] = { .name = "Kbl Audio Headset Playback", .stream_name = "Headset Audio", - .cpu_dai_name = "System Pin2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(system2, dummy, platform), }, [KBL_DPCM_AUDIO_ECHO_REF_CP] = { .name = "Kbl Audio Echo Reference cap", .stream_name = "Echoreference Capture", - .cpu_dai_name = "Echoref Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .capture_only = 1, .nonatomic = 1, + SND_SOC_DAILINK_REG(echoref, dummy, platform), }, [KBL_DPCM_AUDIO_REF_CP] = { .name = "Kbl Audio Reference cap", .stream_name = "Wake on Voice", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [KBL_DPCM_AUDIO_DMIC_CP] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI3_PB] = { .name = "Kbl HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ @@ -718,11 +743,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codecs = max98927_codec_components, - .num_codecs = ARRAY_SIZE(max98927_codec_components), .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -730,16 +751,13 @@ static struct snd_soc_dai_link kabylake_dais[] = { .be_hw_params_fixup = kabylake_ssp_fixup, .dpcm_playback = 1, .ops = &kabylake_ssp0_ops, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { /* SSP1 - Codec */ .name = "SSP1-Codec", .id = 1, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "i2c-10EC5663:00", - .codec_dai_name = KBL_REALTEK_CODEC_DAI, .init = kabylake_rt5663_max98927_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -748,51 +766,40 @@ static struct snd_soc_dai_link kabylake_dais[] = { .ops = &kabylake_rt5663_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "dmic01", .id = 2, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:1f.3", .be_hw_params_fixup = kabylake_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 5, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi3_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; @@ -801,58 +808,46 @@ static struct snd_soc_dai_link kabylake_5663_dais[] = { [KBL_DPCM_AUDIO_5663_PB] = { .name = "Kbl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &kabylake_rt5663_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_5663_CP] = { .name = "Kbl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &kabylake_rt5663_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_5663_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [KBL_DPCM_AUDIO_5663_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, /* Back End DAI links */ @@ -860,11 +855,7 @@ static struct snd_soc_dai_link kabylake_5663_dais[] = { /* SSP1 - Codec */ .name = "SSP1-Codec", .id = 0, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "i2c-10EC5663:00", - .codec_dai_name = KBL_REALTEK_CODEC_DAI, .init = kabylake_rt5663_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -873,28 +864,23 @@ static struct snd_soc_dai_link kabylake_5663_dais[] = { .ops = &kabylake_rt5663_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "iDisp1", .id = 1, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = kabylake_5663_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 2, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = kabylake_5663_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, }; From 42ac21b9b17dfa7dba9a481d0716d50f535fdd5d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:22 +0900 Subject: [PATCH 286/626] ASoC: Intel: kbl_rt5663_rt5514_max98927: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- .../intel/boards/kbl_rt5663_rt5514_max98927.c | 126 +++++++++--------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 879f14257a3e..a22749e48943 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -145,20 +145,6 @@ static struct snd_soc_codec_conf max98927_codec_conf[] = { }, }; -static struct snd_soc_dai_link_component ssp0_codec_components[] = { - { /* Left */ - .name = MAXIM_DEV0_NAME, - .dai_name = KBL_MAXIM_CODEC_DAI, - }, - { /* Right */ - .name = MAXIM_DEV1_NAME, - .dai_name = KBL_MAXIM_CODEC_DAI, - }, - { /*dmic */ - .name = RT5514_DEV_NAME, - .dai_name = KBL_REALTEK_DMIC_CODEC_DAI, - }, -}; static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) { @@ -430,108 +416,136 @@ static struct snd_soc_ops kabylake_dmic_ops = { .startup = kabylake_dmic_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(system2, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); + +SND_SOC_DAILINK_DEF(echoref, + DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin"))); + +SND_SOC_DAILINK_DEF(spi_cpu, + DAILINK_COMP_ARRAY(COMP_CPU("spi-PRP0001:00"))); +SND_SOC_DAILINK_DEF(spi_platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("spi-PRP0001:00"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY( + /* Left */ COMP_CODEC(MAXIM_DEV0_NAME, KBL_MAXIM_CODEC_DAI), + /* Right */COMP_CODEC(MAXIM_DEV1_NAME, KBL_MAXIM_CODEC_DAI), + /* dmic */ COMP_CODEC(RT5514_DEV_NAME, KBL_REALTEK_DMIC_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(ssp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); +SND_SOC_DAILINK_DEF(ssp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC(RT5663_DEV_NAME, KBL_REALTEK_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* kabylake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link kabylake_dais[] = { /* Front End DAI links */ [KBL_DPCM_AUDIO_PB] = { .name = "Kbl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = kabylake_rt5663_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &kabylake_rt5663_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_CP] = { .name = "Kbl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &kabylake_rt5663_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_HS_PB] = { .name = "Kbl Audio Headset Playback", .stream_name = "Headset Audio", - .cpu_dai_name = "System Pin2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(system2, dummy, platform), }, [KBL_DPCM_AUDIO_ECHO_REF_CP] = { .name = "Kbl Audio Echo Reference cap", .stream_name = "Echoreference Capture", - .cpu_dai_name = "Echoref Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .capture_only = 1, .nonatomic = 1, + SND_SOC_DAILINK_REG(echoref, dummy, platform), }, [KBL_DPCM_AUDIO_RT5514_DSP] = { .name = "rt5514 dsp", .stream_name = "Wake on Voice", - .cpu_dai_name = "spi-PRP0001:00", - .platform_name = "spi-PRP0001:00", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", + SND_SOC_DAILINK_REG(spi_cpu, dummy, spi_platform), }, [KBL_DPCM_AUDIO_DMIC_CP] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, /* Back End DAI links */ /* single Back end dai for both max speakers and dmic */ @@ -539,11 +553,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codecs = ssp0_codec_components, - .num_codecs = ARRAY_SIZE(ssp0_codec_components), .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -552,15 +562,12 @@ static struct snd_soc_dai_link kabylake_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .ops = &kabylake_ssp0_ops, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { .name = "SSP1-Codec", .id = 1, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = RT5663_DEV_NAME, - .codec_dai_name = KBL_REALTEK_CODEC_DAI, .init = kabylake_rt5663_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -569,28 +576,23 @@ static struct snd_soc_dai_link kabylake_dais[] = { .ops = &kabylake_rt5663_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, }; From bf2a8ebd07f7d69d20cf2310b61357026a418c20 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:26 +0900 Subject: [PATCH 287/626] ASoC: Intel: kbl_da7219_max98927: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_da7219_max98927.c | 212 ++++++++----------- 1 file changed, 90 insertions(+), 122 deletions(-) diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index d6765c359449..829f95fc4179 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -594,19 +594,6 @@ static struct snd_soc_codec_conf max98373_codec_conf[] = { }, }; -static struct snd_soc_dai_link_component max98927_ssp0_codec_components[] = { - { /* Left */ - .name = MAX98927_DEV0_NAME, - .dai_name = MAX98927_CODEC_DAI, - }, - - { /* For Right */ - .name = MAX98927_DEV1_NAME, - .dai_name = MAX98927_CODEC_DAI, - }, - -}; - static struct snd_soc_dai_link_component max98373_ssp0_codec_components[] = { { /* Left */ .name = MAX98373_DEV0_NAME, @@ -620,110 +607,148 @@ static struct snd_soc_dai_link_component max98373_ssp0_codec_components[] = { }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(echoref, + DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin"))); + +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(system2, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY( + /* Left */ COMP_CODEC(MAX98927_DEV0_NAME, MAX98927_CODEC_DAI), + /* For Right */ COMP_CODEC(MAX98927_DEV1_NAME, MAX98927_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(ssp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); +SND_SOC_DAILINK_DEF(ssp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", + KBL_DIALOG_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(dmic_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* kabylake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link kabylake_dais[] = { /* Front End DAI links */ [KBL_DPCM_AUDIO_PB] = { .name = "Kbl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = kabylake_da7219_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &kabylake_da7219_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_ECHO_REF_CP] = { .name = "Kbl Audio Echo Reference cap", .stream_name = "Echoreference Capture", - .cpu_dai_name = "Echoref Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .capture_only = 1, .nonatomic = 1, + SND_SOC_DAILINK_REG(echoref, dummy, platform), }, [KBL_DPCM_AUDIO_REF_CP] = { .name = "Kbl Audio Reference cap", .stream_name = "Wake on Voice", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [KBL_DPCM_AUDIO_DMIC_CP] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI3_PB] = { .name = "Kbl HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, [KBL_DPCM_AUDIO_HS_PB] = { .name = "Kbl Audio Headset Playback", .stream_name = "Headset Audio", - .cpu_dai_name = "System Pin2", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .nonatomic = 1, .dynamic = 1, @@ -731,21 +756,18 @@ static struct snd_soc_dai_link kabylake_dais[] = { .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ops = &kabylake_da7219_fe_ops, - + SND_SOC_DAILINK_REG(system2, dummy, platform), }, [KBL_DPCM_AUDIO_CP] = { .name = "Kbl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &kabylake_da7219_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, /* Back End DAI links */ @@ -753,11 +775,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codecs = max98927_ssp0_codec_components, - .num_codecs = ARRAY_SIZE(max98927_ssp0_codec_components), .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -766,16 +784,13 @@ static struct snd_soc_dai_link kabylake_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, .ops = &kabylake_ssp0_ops, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { /* SSP1 - Codec */ .name = "SSP1-Codec", .id = 1, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "i2c-DLGS7219:00", - .codec_dai_name = KBL_DIALOG_CODEC_DAI, .init = kabylake_da7219_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -783,52 +798,41 @@ static struct snd_soc_dai_link kabylake_dais[] = { .be_hw_params_fixup = kabylake_ssp_fixup, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "dmic01", .id = 2, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", .init = kabylake_dmic_init, - .platform_name = "0000:00:1f.3", .be_hw_params_fixup = kabylake_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 5, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi3_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; @@ -838,96 +842,75 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { [KBL_DPCM_AUDIO_PB] = { .name = "Kbl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = kabylake_da7219_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &kabylake_da7219_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_ECHO_REF_CP] = { .name = "Kbl Audio Echo Reference cap", .stream_name = "Echoreference Capture", - .cpu_dai_name = "Echoref Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .capture_only = 1, .nonatomic = 1, + SND_SOC_DAILINK_REG(echoref, dummy, platform), }, [KBL_DPCM_AUDIO_REF_CP] = { .name = "Kbl Audio Reference cap", .stream_name = "Wake on Voice", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [KBL_DPCM_AUDIO_DMIC_CP] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI3_PB] = { .name = "Kbl HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ @@ -935,11 +918,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codecs = max98927_ssp0_codec_components, - .num_codecs = ARRAY_SIZE(max98927_ssp0_codec_components), .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -948,52 +927,41 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, .ops = &kabylake_ssp0_ops, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec), }, { .name = "dmic01", .id = 1, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", .init = kabylake_dmic_init, - .platform_name = "0000:00:1f.3", .be_hw_params_fixup = kabylake_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 2, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 3, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 4, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi3_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; From 27eb6c7cb9027c4f0bb3a1b98659c1376b91d46c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:31 +0900 Subject: [PATCH 288/626] ASoC: Intel: kbl_da7219_max98357a: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_da7219_max98357a.c | 114 ++++++++++-------- 1 file changed, 66 insertions(+), 48 deletions(-) diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index 4e5db2241fb9..537a88932bb6 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -349,92 +349,128 @@ static const unsigned int ch_mono[] = { 1, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY(COMP_CODEC(MAXIM_DEV0_NAME, + KBL_MAXIM_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(ssp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); +SND_SOC_DAILINK_DEF(ssp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", + KBL_DIALOG_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(dmic_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", + "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* kabylake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link kabylake_dais[] = { /* Front End DAI links */ [KBL_DPCM_AUDIO_PB] = { .name = "Kbl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = kabylake_da7219_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &kabylake_da7219_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_CP] = { .name = "Kbl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &kabylake_da7219_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_DMIC_CP] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI3_PB] = { .name = "Kbl HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ @@ -442,27 +478,20 @@ static struct snd_soc_dai_link kabylake_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = MAXIM_DEV0_NAME, - .codec_dai_name = KBL_MAXIM_CODEC_DAI, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { /* SSP1 - Codec */ .name = "SSP1-Codec", .id = 1, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "i2c-DLGS7219:00", - .codec_dai_name = KBL_DIALOG_CODEC_DAI, .init = kabylake_da7219_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -470,51 +499,40 @@ static struct snd_soc_dai_link kabylake_dais[] = { .be_hw_params_fixup = kabylake_ssp_fixup, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "dmic01", .id = 2, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:1f.3", .be_hw_params_fixup = kabylake_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 5, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:1f.3", .init = kabylake_hdmi3_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; From 502a522b7b8b98bd453ef948dbe47eddc787826c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:36 +0900 Subject: [PATCH 289/626] ASoC: Intel: skl_nau88l25_ssm4567: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 132 +++++++++--------- 1 file changed, 69 insertions(+), 63 deletions(-) diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index 8433c521d39f..36ab838c77f1 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -164,17 +164,6 @@ static struct snd_soc_codec_conf ssm4567_codec_conf[] = { }, }; -static struct snd_soc_dai_link_component ssm4567_codec_components[] = { - { /* Left */ - .name = "i2c-INT343B:00", - .dai_name = SKL_SSM_CODEC_DAI, - }, - { /* Right */ - .name = "i2c-INT343B:01", - .dai_name = SKL_SSM_CODEC_DAI, - }, -}; - static int skylake_ssm4567_codec_init(struct snd_soc_pcm_runtime *rtd) { int ret; @@ -453,105 +442,140 @@ static const struct snd_soc_ops skylake_refcap_ops = { .startup = skylake_refcap_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY( + /* Left */ COMP_CODEC("i2c-INT343B:00", SKL_SSM_CODEC_DAI), + /* Right */ COMP_CODEC("i2c-INT343B:01", SKL_SSM_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(ssp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); +SND_SOC_DAILINK_DEF(ssp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", SKL_NUVOTON_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(dmic01_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* skylake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link skylake_dais[] = { /* Front End DAI links */ [SKL_DPCM_AUDIO_PB] = { .name = "Skl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = skylake_nau8825_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &skylake_nau8825_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [SKL_DPCM_AUDIO_CP] = { .name = "Skl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &skylake_nau8825_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [SKL_DPCM_AUDIO_REF_CP] = { .name = "Skl Audio Reference cap", .stream_name = "Wake on Voice", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [SKL_DPCM_AUDIO_DMIC_CP] = { .name = "Skl Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI1_PB] = { .name = "Skl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI2_PB] = { .name = "Skl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI3_PB] = { .name = "Skl HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ @@ -559,11 +583,7 @@ static struct snd_soc_dai_link skylake_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codecs = ssm4567_codec_components, - .num_codecs = ARRAY_SIZE(ssm4567_codec_components), .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -572,16 +592,13 @@ static struct snd_soc_dai_link skylake_dais[] = { .be_hw_params_fixup = skylake_ssp_fixup, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { /* SSP1 - Codec */ .name = "SSP1-Codec", .id = 1, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "i2c-10508825:00", - .codec_dai_name = SKL_NUVOTON_CODEC_DAI, .init = skylake_nau8825_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -590,51 +607,40 @@ static struct snd_soc_dai_link skylake_dais[] = { .ops = &skylake_nau8825_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "dmic01", .id = 2, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:1f.3", .ignore_suspend = 1, .be_hw_params_fixup = skylake_dmic_fixup, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = skylake_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = skylake_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 5, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:1f.3", .init = skylake_hdmi3_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; From 9cb56a5ceefaa8d4b8d69d6a4a5d9d0c7964374a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:41 +0900 Subject: [PATCH 290/626] ASoC: Intel: skl_rt286: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_rt286.c | 118 ++++++++++++++++------------- 1 file changed, 65 insertions(+), 53 deletions(-) diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 0e1818dd4cc6..1f47ac2f8add 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -291,18 +291,66 @@ static const struct snd_soc_ops skylake_dmic_ops = { .startup = skylake_dmic_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("Deepbuffer Pin"))); + +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00", "rt286-aif1"))); + +SND_SOC_DAILINK_DEF(dmic01_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* skylake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link skylake_rt286_dais[] = { /* Front End DAI links */ [SKL_DPCM_AUDIO_PB] = { .name = "Skl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .nonatomic = 1, .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .init = skylake_rt286_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, @@ -310,100 +358,79 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { }, .dpcm_playback = 1, .ops = &skylake_rt286_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [SKL_DPCM_AUDIO_DB_PB] = { .name = "Skl Deepbuffer Port", .stream_name = "Deep Buffer Audio", - .cpu_dai_name = "Deepbuffer Pin", - .platform_name = "0000:00:1f.3", .nonatomic = 1, .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST }, .dpcm_playback = 1, .ops = &skylake_rt286_fe_ops, - + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, [SKL_DPCM_AUDIO_CP] = { .name = "Skl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .nonatomic = 1, .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST }, .dpcm_capture = 1, .ops = &skylake_rt286_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [SKL_DPCM_AUDIO_REF_CP] = { .name = "Skl Audio Reference cap", .stream_name = "refcap", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [SKL_DPCM_AUDIO_DMIC_CP] = { .name = "Skl Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI1_PB] = { .name = "Skl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI2_PB] = { .name = "Skl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI3_PB] = { .name = "Skl HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ @@ -411,11 +438,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "i2c-INT343A:00", - .codec_dai_name = "rt286-aif1", .init = skylake_rt286_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | @@ -425,51 +448,40 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .ops = &skylake_rt286_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { .name = "dmic01", .id = 1, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:1f.3", .be_hw_params_fixup = skylake_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 2, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .init = skylake_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 3, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = skylake_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 4, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:1f.3", .init = skylake_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; From 318796d854ff57ec9a60fd002f8514ed872a4f0e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:46 +0900 Subject: [PATCH 291/626] ASoC: Intel: skl_nau88l25_max98357a: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- .../soc/intel/boards/skl_nau88l25_max98357a.c | 120 ++++++++++-------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 0922106bd323..872223163718 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -404,105 +404,139 @@ static const struct snd_soc_ops skylake_refcap_ops = { .startup = skylake_refcap_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", SKL_MAXIM_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(ssp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); +SND_SOC_DAILINK_DEF(ssp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", + SKL_NUVOTON_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(dmic_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* skylake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link skylake_dais[] = { /* Front End DAI links */ [SKL_DPCM_AUDIO_PB] = { .name = "Skl Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = skylake_nau8825_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .ops = &skylake_nau8825_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [SKL_DPCM_AUDIO_CP] = { .name = "Skl Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:1f.3", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, .ops = &skylake_nau8825_fe_ops, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [SKL_DPCM_AUDIO_REF_CP] = { .name = "Skl Audio Reference cap", .stream_name = "Wake on Voice", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [SKL_DPCM_AUDIO_DMIC_CP] = { .name = "Skl Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI1_PB] = { .name = "Skl HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI2_PB] = { .name = "Skl HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [SKL_DPCM_AUDIO_HDMI3_PB] = { .name = "Skl HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:1f.3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ @@ -510,27 +544,20 @@ static struct snd_soc_dai_link skylake_dais[] = { /* SSP0 - Codec */ .name = "SSP0-Codec", .id = 0, - .cpu_dai_name = "SSP0 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "MX98357A:00", - .codec_dai_name = SKL_MAXIM_CODEC_DAI, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_pmdown_time = 1, .be_hw_params_fixup = skylake_ssp_fixup, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { /* SSP1 - Codec */ .name = "SSP1-Codec", .id = 1, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:1f.3", .no_pcm = 1, - .codec_name = "i2c-10508825:00", - .codec_dai_name = SKL_NUVOTON_CODEC_DAI, .init = skylake_nau8825_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -539,51 +566,40 @@ static struct snd_soc_dai_link skylake_dais[] = { .ops = &skylake_nau8825_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "dmic01", .id = 2, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:1f.3", .be_hw_params_fixup = skylake_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .init = skylake_hdmi1_init, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:1f.3", .init = skylake_hdmi2_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 5, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:1f.3", .init = skylake_hdmi3_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; From 2bfa8c35d90c2f3f6fc1814d37bc80f13246a762 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:21:51 +0900 Subject: [PATCH 292/626] ASoC: Intel: skl-pcm: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 9735e2412251..edc5ecfc0b55 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1085,7 +1085,7 @@ static int skl_platform_open(struct snd_pcm_substream *substream) struct snd_soc_dai_link *dai_link = rtd->dai_link; dev_dbg(rtd->cpu_dai->dev, "In %s:%s\n", __func__, - dai_link->cpu_dai_name); + dai_link->cpus->dai_name); snd_soc_set_runtime_hwparams(substream, &azx_pcm_hw); From a78959f407e66b2f74fb72b47b252f4ed8b1671e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:22:04 +0900 Subject: [PATCH 293/626] ASoC: Intel: skl_hda_dsp_common: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_common.c | 66 ++++++++++++-------- sound/soc/intel/boards/skl_hda_dsp_generic.c | 4 +- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c index 82f10bf2abb2..55fd82e05e2c 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.c +++ b/sound/soc/intel/boards/skl_hda_dsp_common.c @@ -38,77 +38,93 @@ int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device) return 0; } +SND_SOC_DAILINK_DEFS(idisp1, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")), + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEFS(idisp2, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")), + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEFS(idisp3, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")), + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(analog_cpu, + DAILINK_COMP_ARRAY(COMP_CPU("Analog CPU DAI"))); +SND_SOC_DAILINK_DEF(analog_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Analog Codec DAI"))); + +SND_SOC_DAILINK_DEF(digital_cpu, + DAILINK_COMP_ARRAY(COMP_CPU("Digital CPU DAI"))); +SND_SOC_DAILINK_DEF(digital_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Digital Codec DAI"))); + +SND_SOC_DAILINK_DEF(dmic_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); + +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(dmic16k, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + /* skl_hda_digital audio interface glue - connects codec <--> CPU */ struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS] = { /* Back End DAI links */ { .name = "iDisp1", .id = 1, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1), }, { .name = "iDisp2", .id = 2, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2), }, { .name = "iDisp3", .id = 3, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3), }, { .name = "Analog Playback and Capture", .id = 4, - .cpu_dai_name = "Analog CPU DAI", - .codec_name = "ehdaudio0D0", - .codec_dai_name = "Analog Codec DAI", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(analog_cpu, analog_codec, platform), }, { .name = "Digital Playback and Capture", .id = 5, - .cpu_dai_name = "Digital CPU DAI", - .codec_name = "ehdaudio0D0", - .codec_dai_name = "Digital Codec DAI", - .platform_name = "0000:00:1f.3", .dpcm_playback = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(digital_cpu, digital_codec, platform), }, { .name = "dmic01", .id = 6, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:1f.3", .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "dmic16k", .id = 7, - .cpu_dai_name = "DMIC16k Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:1f.3", .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform), }, }; diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index fc52d3a32354..9ed68eb4f058 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -69,7 +69,7 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) int ret = 0; dev_dbg(card->dev, "%s: dai link name - %s\n", __func__, link->name); - link->platform_name = ctx->platform_name; + link->platforms->name = ctx->platform_name; link->nonatomic = 1; if (strstr(link->name, "HDMI")) { @@ -142,7 +142,7 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) card->num_dapm_routes = num_route; for_each_card_prelinks(card, i, dai_link) - dai_link->platform_name = mach_params->platform; + dai_link->platforms->name = mach_params->platform; return 0; } From 02c31963d156025be6264d88ee42f78091112ca5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:22:09 +0900 Subject: [PATCH 294/626] ASoC: Intel: glk_rt5682_max98357a: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/intel/boards/glk_rt5682_max98357a.c | 137 ++++++++++-------- 1 file changed, 77 insertions(+), 60 deletions(-) diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index 7180100a9084..bd2d371f2acd 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -317,152 +317,180 @@ static const struct snd_soc_ops geminilake_refcap_ops = { .startup = geminilake_refcap_startup, }; +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(system, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); + +SND_SOC_DAILINK_DEF(system2, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); + +SND_SOC_DAILINK_DEF(echoref, + DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin"))); + +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + +SND_SOC_DAILINK_DEF(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); + +SND_SOC_DAILINK_DEF(hdmi1, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi2, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); + +SND_SOC_DAILINK_DEF(hdmi3, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); + +SND_SOC_DAILINK_DEF(ssp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); +SND_SOC_DAILINK_DEF(ssp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC(MAXIM_DEV0_NAME, + GLK_MAXIM_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(ssp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin"))); +SND_SOC_DAILINK_DEF(ssp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", + GLK_REALTEK_CODEC_DAI))); + +SND_SOC_DAILINK_DEF(dmic_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(idisp1_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); +SND_SOC_DAILINK_DEF(idisp1_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); + +SND_SOC_DAILINK_DEF(idisp2_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); +SND_SOC_DAILINK_DEF(idisp2_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); + +SND_SOC_DAILINK_DEF(idisp3_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); +SND_SOC_DAILINK_DEF(idisp3_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0"))); + /* geminilake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link geminilake_dais[] = { /* Front End DAI links */ [GLK_DPCM_AUDIO_PB] = { .name = "Glk Audio Port", .stream_name = "Audio", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:0e.0", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .init = geminilake_rt5682_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [GLK_DPCM_AUDIO_CP] = { .name = "Glk Audio Capture Port", .stream_name = "Audio Record", - .cpu_dai_name = "System Pin", - .platform_name = "0000:00:0e.0", .dynamic = 1, - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(system, dummy, platform), }, [GLK_DPCM_AUDIO_HS_PB] = { .name = "Glk Audio Headset Playback", .stream_name = "Headset Audio", - .cpu_dai_name = "System Pin2", - .platform_name = "0000:00:0e.0", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .dpcm_playback = 1, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(system2, dummy, platform), }, [GLK_DPCM_AUDIO_ECHO_REF_CP] = { .name = "Glk Audio Echo Reference cap", .stream_name = "Echoreference Capture", - .cpu_dai_name = "Echoref Pin", - .platform_name = "0000:00:0e.0", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .init = NULL, .capture_only = 1, .nonatomic = 1, + SND_SOC_DAILINK_REG(echoref, dummy, platform), }, [GLK_DPCM_AUDIO_REF_CP] = { .name = "Glk Audio Reference cap", .stream_name = "Refcap", - .cpu_dai_name = "Reference Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &geminilake_refcap_ops, + SND_SOC_DAILINK_REG(reference, dummy, platform), }, [GLK_DPCM_AUDIO_DMIC_CP] = { .name = "Glk Audio DMIC cap", .stream_name = "dmiccap", - .cpu_dai_name = "DMIC Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .init = NULL, .dpcm_capture = 1, .nonatomic = 1, .dynamic = 1, .ops = &geminilake_dmic_ops, + SND_SOC_DAILINK_REG(dmic, dummy, platform), }, [GLK_DPCM_AUDIO_HDMI1_PB] = { .name = "Glk HDMI Port1", .stream_name = "Hdmi1", - .cpu_dai_name = "HDMI1 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi1, dummy, platform), }, [GLK_DPCM_AUDIO_HDMI2_PB] = { .name = "Glk HDMI Port2", .stream_name = "Hdmi2", - .cpu_dai_name = "HDMI2 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi2, dummy, platform), }, [GLK_DPCM_AUDIO_HDMI3_PB] = { .name = "Glk HDMI Port3", .stream_name = "Hdmi3", - .cpu_dai_name = "HDMI3 Pin", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .platform_name = "0000:00:0e.0", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hdmi3, dummy, platform), }, /* Back End DAI links */ { /* SSP1 - Codec */ .name = "SSP1-Codec", .id = 0, - .cpu_dai_name = "SSP1 Pin", - .platform_name = "0000:00:0e.0", .no_pcm = 1, - .codec_name = MAXIM_DEV0_NAME, - .codec_dai_name = GLK_MAXIM_CODEC_DAI, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_pmdown_time = 1, .be_hw_params_fixup = geminilake_ssp_fixup, .dpcm_playback = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { /* SSP2 - Codec */ .name = "SSP2-Codec", .id = 1, - .cpu_dai_name = "SSP2 Pin", - .platform_name = "0000:00:0e.0", .no_pcm = 1, - .codec_name = "i2c-10EC5682:00", - .codec_dai_name = GLK_REALTEK_CODEC_DAI, .init = geminilake_rt5682_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -471,51 +499,40 @@ static struct snd_soc_dai_link geminilake_dais[] = { .ops = &geminilake_rt5682_ops, .dpcm_playback = 1, .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ssp2_pin, ssp2_codec, platform), }, { .name = "dmic01", .id = 2, - .cpu_dai_name = "DMIC01 Pin", - .codec_name = "dmic-codec", - .codec_dai_name = "dmic-hifi", - .platform_name = "0000:00:0e.0", .ignore_suspend = 1, .be_hw_params_fixup = geminilake_dmic_fixup, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .cpu_dai_name = "iDisp1 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi1", - .platform_name = "0000:00:0e.0", .init = geminilake_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, { .name = "iDisp2", .id = 4, - .cpu_dai_name = "iDisp2 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi2", - .platform_name = "0000:00:0e.0", .init = geminilake_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, { .name = "iDisp3", .id = 5, - .cpu_dai_name = "iDisp3 Pin", - .codec_name = "ehdaudio0D2", - .codec_dai_name = "intel-hdmi-hifi3", - .platform_name = "0000:00:0e.0", .init = geminilake_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, }; From e1684073ef2142c241375487b1e158abe169ce61 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:22:14 +0900 Subject: [PATCH 295/626] ASoC: Intel: sof_rt5682: use modern dai_link style ASoC is now supporting modern style dai_link (= snd_soc_dai_link_component) for CPU/Codec/Platform. This patch switches to use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 57 +++++++++++++++++------------ 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 355fd9730a44..e2e5f97d9920 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -331,12 +331,15 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, int hdmi_num) { struct snd_soc_dai_link_component *idisp_components; + struct snd_soc_dai_link_component *cpus; struct snd_soc_dai_link *links; int i, id = 0; links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * sof_audio_card_rt5682.num_links, GFP_KERNEL); - if (!links) + cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) * + sof_audio_card_rt5682.num_links, GFP_KERNEL); + if (!links || !cpus) goto devm_err; /* codec SSP */ @@ -356,11 +359,13 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].dpcm_playback = 1; links[id].dpcm_capture = 1; links[id].no_pcm = 1; + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; if (is_legacy_cpu) { - links[id].cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, - "ssp%d-port", - ssp_codec); - if (!links[id].cpu_dai_name) + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "ssp%d-port", + ssp_codec); + if (!links[id].cpus->dai_name) goto devm_err; } else { /* @@ -373,10 +378,10 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, * It can be removed once we can control MCLK by driver. */ links[id].ignore_pmdown_time = 1; - links[id].cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d Pin", - ssp_codec); - if (!links[id].cpu_dai_name) + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", + ssp_codec); + if (!links[id].cpus->dai_name) goto devm_err; } id++; @@ -389,9 +394,11 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, goto devm_err; links[id].id = id; - links[id].cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, - "DMIC%02d Pin", i); - if (!links[id].cpu_dai_name) + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "DMIC%02d Pin", i); + if (!links[id].cpus->dai_name) goto devm_err; links[id].codecs = dmic_component; @@ -419,9 +426,11 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, goto devm_err; links[id].id = id; - links[id].cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, - "iDisp%d Pin", i); - if (!links[id].cpu_dai_name) + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "iDisp%d Pin", i); + if (!links[id].cpus->dai_name) goto devm_err; idisp_components[i - 1].name = "ehdaudio0D2"; @@ -458,18 +467,20 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].nonatomic = true; links[id].dpcm_playback = 1; links[id].no_pcm = 1; + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; if (is_legacy_cpu) { - links[id].cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, - "ssp%d-port", - ssp_amp); - if (!links[id].cpu_dai_name) + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "ssp%d-port", + ssp_amp); + if (!links[id].cpus->dai_name) goto devm_err; } else { - links[id].cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d Pin", - ssp_amp); - if (!links[id].cpu_dai_name) + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", + ssp_amp); + if (!links[id].cpus->dai_name) goto devm_err; } } From adb76b5b9c4740a11f6ad6c68764515961ae8ade Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Jun 2019 13:22:19 +0900 Subject: [PATCH 296/626] ASoC: soc-core: remove legacy style dai_link All drivers switched to modern style dai_link (= struct snd_soc_dai_link_component). Let's remove legacy style dai_link. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 65 ++--------------- sound/soc/soc-core.c | 165 ++----------------------------------------- 2 files changed, 12 insertions(+), 218 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 0fa79b8330d7..055e6d035e04 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -900,17 +900,6 @@ struct snd_soc_dai_link { const char *name; /* Codec name */ const char *stream_name; /* Stream name */ - /* - * cpu_name - * cpu_of_node - * cpu_dai_name - * - * These are legacy style, and will be replaced to - * modern style (= snd_soc_dai_link_component) in the future, - * but, not yet supported so far. - * If modern style was supported for CPU, all driver will switch - * to use it, and, legacy style code will be removed from ALSA SoC. - */ /* * You MAY specify the link's CPU-side device, either by device name, * or by DT/OF node, but not both. If this information is omitted, @@ -918,60 +907,27 @@ struct snd_soc_dai_link { * must be globally unique. These fields are currently typically used * only for codec to codec links, or systems using device tree. */ - const char *cpu_name; - struct device_node *cpu_of_node; /* * You MAY specify the DAI name of the CPU DAI. If this information is * omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node * only, which only works well when that device exposes a single DAI. */ - const char *cpu_dai_name; - struct snd_soc_dai_link_component *cpus; unsigned int num_cpus; - /* - * codec_name - * codec_of_node - * codec_dai_name - * - * These are legacy style, it will be converted to modern style - * (= snd_soc_dai_link_component) automatically in soc-core - * if driver is using legacy style. - * Driver shouldn't use both legacy and modern style in the same time. - * If modern style was supported for CPU, all driver will switch - * to use it, and, legacy style code will be removed from ALSA SoC. - */ /* * You MUST specify the link's codec, either by device name, or by * DT/OF node, but not both. */ - const char *codec_name; - struct device_node *codec_of_node; /* You MUST specify the DAI name within the codec */ - const char *codec_dai_name; - struct snd_soc_dai_link_component *codecs; unsigned int num_codecs; - /* - * platform_name - * platform_of_node - * - * These are legacy style, it will be converted to modern style - * (= snd_soc_dai_link_component) automatically in soc-core - * if driver is using legacy style. - * Driver shouldn't use both legacy and modern style in the same time. - * If modern style was supported for CPU, all driver will switch - * to use it, and, legacy style code will be removed from ALSA SoC. - */ /* * You MAY specify the link's platform/PCM/DMA driver, either by * device name, or by DT/OF node, but not both. Some forms of link * do not need a platform. */ - const char *platform_name; - struct device_node *platform_of_node; struct snd_soc_dai_link_component *platforms; unsigned int num_platforms; @@ -1033,13 +989,6 @@ struct snd_soc_dai_link { /* Do not create a PCM for this DAI link (Backend link) */ unsigned int ignore:1; - /* - * This driver uses legacy platform naming. Set by the core, machine - * drivers should not modify this value. - */ - unsigned int legacy_platform:1; - unsigned int legacy_cpu:1; - struct list_head list; /* DAI link list of the soc card */ struct snd_soc_dobj dobj; /* For topology */ }; @@ -1699,15 +1648,11 @@ int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card, if (!name) return -ENOMEM; - if (dai_link->platforms) - /* only single platform is supported for now */ - dai_link->platforms->name = name; - else - /* - * legacy mode, this case will be removed when all - * derivers are switched to modern style dai_link. - */ - dai_link->platform_name = name; + if (!dai_link->platforms) + return -EINVAL; + + /* only single platform is supported for now */ + dai_link->platforms->name = name; } return 0; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9bd6b08d79b5..f8426c8120b2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1053,167 +1053,18 @@ static void soc_remove_dai_links(struct snd_soc_card *card) } } -static int snd_soc_init_cpu(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_link) -{ - struct snd_soc_dai_link_component *cpu = dai_link->cpus; - - /* - * REMOVE ME - * - * This is glue code for Legacy vs Modern dai_link. - * This function will be removed if all derivers are switched to - * modern style dai_link. - * Driver shouldn't use both legacy and modern style in the same time. - * see - * soc.h :: struct snd_soc_dai_link - */ - /* convert Legacy platform link */ - if (!cpu) { - cpu = devm_kzalloc(card->dev, - sizeof(struct snd_soc_dai_link_component), - GFP_KERNEL); - if (!cpu) - return -ENOMEM; - - dai_link->cpus = cpu; - dai_link->num_cpus = 1; - dai_link->legacy_cpu = 1; - - cpu->name = dai_link->cpu_name; - cpu->of_node = dai_link->cpu_of_node; - cpu->dai_name = dai_link->cpu_dai_name; - } - - if (!dai_link->cpus) { - dev_err(card->dev, "ASoC: DAI link has no CPUs\n"); - return -EINVAL; - } - - return 0; -} - -static int snd_soc_init_platform(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_link) -{ - struct snd_soc_dai_link_component *platform = dai_link->platforms; - - /* - * REMOVE ME - * - * This is glue code for Legacy vs Modern dai_link. - * This function will be removed if all derivers are switched to - * modern style dai_link. - * Driver shouldn't use both legacy and modern style in the same time. - * see - * soc.h :: struct snd_soc_dai_link - */ - /* convert Legacy platform link */ - if (!platform) { - platform = devm_kzalloc(card->dev, - sizeof(struct snd_soc_dai_link_component), - GFP_KERNEL); - if (!platform) - return -ENOMEM; - - dai_link->platforms = platform; - dai_link->num_platforms = 1; - dai_link->legacy_platform = 1; - platform->name = dai_link->platform_name; - platform->of_node = dai_link->platform_of_node; - platform->dai_name = NULL; - } - - /* if there's no platform we match on the empty platform */ - if (!platform->name && - !platform->of_node) - platform->name = "snd-soc-dummy"; - - return 0; -} - -static void soc_cleanup_legacy(struct snd_soc_card *card) -{ - struct snd_soc_dai_link *link; - int i; - /* - * FIXME - * - * this function should be removed with snd_soc_init_platform - */ - - for_each_card_prelinks(card, i, link) { - if (link->legacy_platform) { - link->legacy_platform = 0; - link->platforms = NULL; - } - if (link->legacy_cpu) { - link->legacy_cpu = 0; - link->cpus = NULL; - } - } -} - -static int snd_soc_init_multicodec(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_link) -{ - /* - * REMOVE ME - * - * This is glue code for Legacy vs Modern dai_link. - * This function will be removed if all derivers are switched to - * modern style dai_link. - * Driver shouldn't use both legacy and modern style in the same time. - * see - * soc.h :: struct snd_soc_dai_link - */ - - /* Legacy codec/codec_dai link is a single entry in multicodec */ - if (dai_link->codec_name || dai_link->codec_of_node || - dai_link->codec_dai_name) { - dai_link->num_codecs = 1; - - dai_link->codecs = devm_kzalloc(card->dev, - sizeof(struct snd_soc_dai_link_component), - GFP_KERNEL); - if (!dai_link->codecs) - return -ENOMEM; - - dai_link->codecs[0].name = dai_link->codec_name; - dai_link->codecs[0].of_node = dai_link->codec_of_node; - dai_link->codecs[0].dai_name = dai_link->codec_dai_name; - } - - if (!dai_link->codecs) { - dev_err(card->dev, "ASoC: DAI link has no CODECs\n"); - return -EINVAL; - } - - return 0; -} +static struct snd_soc_dai_link_component dummy_link = COMP_DUMMY(); static int soc_init_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) { - int i, ret; + int i; struct snd_soc_dai_link_component *codec; - ret = snd_soc_init_cpu(card, link); - if (ret) { - dev_err(card->dev, "ASoC: failed to init cpu\n"); - return ret; - } - - ret = snd_soc_init_platform(card, link); - if (ret) { - dev_err(card->dev, "ASoC: failed to init multiplatform\n"); - return ret; - } - - ret = snd_soc_init_multicodec(card, link); - if (ret) { - dev_err(card->dev, "ASoC: failed to init multicodec\n"); - return ret; + /* default Platform */ + if (!link->platforms || !link->num_platforms) { + link->platforms = &dummy_link; + link->num_platforms = 1; } for_each_link_codecs(link, i, codec) { @@ -2060,7 +1911,7 @@ match: card->dai_link[i].name); /* override platform component */ - if (snd_soc_init_platform(card, dai_link) < 0) { + if (!dai_link->platforms) { dev_err(card->dev, "init platform error"); continue; } @@ -2111,7 +1962,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) /* remove and free each DAI */ soc_remove_dai_links(card); soc_remove_pcm_runtimes(card); - soc_cleanup_legacy(card); /* remove auxiliary devices */ soc_remove_aux_devices(card); @@ -2868,7 +2718,6 @@ int snd_soc_register_card(struct snd_soc_card *card) ret = soc_init_dai_link(card, link); if (ret) { - soc_cleanup_legacy(card); dev_err(card->dev, "ASoC: failed to init link %s\n", link->name); mutex_unlock(&client_mutex); From ef8a4757a6dbb2d406d7ba3a10a513f16f49ed2d Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 6 Jun 2019 13:42:42 +0100 Subject: [PATCH 297/626] ASoC: msm8916-wcd-digital: Add sidetone support This patch adds sidetone support via one of the 3 RX Mix paths using IIR1 and IIR2. IIR1 can be feed by any Decimators or RX paths, and IIRx can also be looped back to RX mixers to provide sidetone functionality. Two IIR filters are used for Side tone equalization and each filter is 5 stage. Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/codecs/msm8916-wcd-digital.c | 282 +++++++++++++++++++++++++ 1 file changed, 282 insertions(+) diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index a63961861e55..1db7e43ec203 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c @@ -187,6 +187,43 @@ #define MSM8916_WCD_DIGITAL_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S32_LE) +/* Codec supports 2 IIR filters */ +enum { + IIR1 = 0, + IIR2, + IIR_MAX, +}; + +/* Codec supports 5 bands */ +enum { + BAND1 = 0, + BAND2, + BAND3, + BAND4, + BAND5, + BAND_MAX, +}; + +#define WCD_IIR_FILTER_SIZE (sizeof(u32)*BAND_MAX) + +#define WCD_IIR_FILTER_CTL(xname, iidx, bidx) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = wcd_iir_filter_info, \ + .get = msm8x16_wcd_get_iir_band_audio_mixer, \ + .put = msm8x16_wcd_put_iir_band_audio_mixer, \ + .private_value = (unsigned long)&(struct wcd_iir_filter_ctl) { \ + .iir_idx = iidx, \ + .band_idx = bidx, \ + .bytes_ext = {.max = WCD_IIR_FILTER_SIZE, }, \ + } \ +} + +struct wcd_iir_filter_ctl { + unsigned int iir_idx; + unsigned int band_idx; + struct soc_bytes_ext bytes_ext; +}; + struct msm8916_wcd_digital_priv { struct clk *ahbclk, *mclk; }; @@ -298,6 +335,161 @@ static SOC_ENUM_SINGLE_DECL(rx2_dcb_cutoff_enum, LPASS_CDC_RX2_B4_CTL, 0, static SOC_ENUM_SINGLE_DECL(rx3_dcb_cutoff_enum, LPASS_CDC_RX3_B4_CTL, 0, dc_blocker_cutoff_text); +static int msm8x16_wcd_codec_set_iir_gain(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int value = 0, reg = 0; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (w->shift == 0) + reg = LPASS_CDC_IIR1_GAIN_B1_CTL; + else if (w->shift == 1) + reg = LPASS_CDC_IIR2_GAIN_B1_CTL; + value = snd_soc_component_read32(component, reg); + snd_soc_component_write(component, reg, value); + break; + default: + break; + } + return 0; +} + +static uint32_t get_iir_band_coeff(struct snd_soc_component *component, + int iir_idx, int band_idx, + int coeff_idx) +{ + uint32_t value = 0; + + /* Address does not automatically update if reading */ + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t)) & 0x7F); + + value |= snd_soc_component_read32(component, + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)); + + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 1) & 0x7F); + + value |= (snd_soc_component_read32(component, + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8); + + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 2) & 0x7F); + + value |= (snd_soc_component_read32(component, + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16); + + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 3) & 0x7F); + + /* Mask bits top 2 bits since they are reserved */ + value |= ((snd_soc_component_read32(component, + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) & 0x3f) << 24); + return value; + +} + +static int msm8x16_wcd_get_iir_band_audio_mixer( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wcd_iir_filter_ctl *ctl = + (struct wcd_iir_filter_ctl *)kcontrol->private_value; + struct soc_bytes_ext *params = &ctl->bytes_ext; + int iir_idx = ctl->iir_idx; + int band_idx = ctl->band_idx; + u32 coeff[BAND_MAX]; + + coeff[0] = get_iir_band_coeff(component, iir_idx, band_idx, 0); + coeff[1] = get_iir_band_coeff(component, iir_idx, band_idx, 1); + coeff[2] = get_iir_band_coeff(component, iir_idx, band_idx, 2); + coeff[3] = get_iir_band_coeff(component, iir_idx, band_idx, 3); + coeff[4] = get_iir_band_coeff(component, iir_idx, band_idx, 4); + + memcpy(ucontrol->value.bytes.data, &coeff[0], params->max); + + return 0; +} + +static void set_iir_band_coeff(struct snd_soc_component *component, + int iir_idx, int band_idx, + uint32_t value) +{ + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx), + (value & 0xFF)); + + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx), + (value >> 8) & 0xFF); + + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx), + (value >> 16) & 0xFF); + + /* Mask top 2 bits, 7-8 are reserved */ + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx), + (value >> 24) & 0x3F); +} + +static int msm8x16_wcd_put_iir_band_audio_mixer( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wcd_iir_filter_ctl *ctl = + (struct wcd_iir_filter_ctl *)kcontrol->private_value; + struct soc_bytes_ext *params = &ctl->bytes_ext; + int iir_idx = ctl->iir_idx; + int band_idx = ctl->band_idx; + u32 coeff[BAND_MAX]; + + memcpy(&coeff[0], ucontrol->value.bytes.data, params->max); + + /* Mask top bit it is reserved */ + /* Updates addr automatically for each B2 write */ + snd_soc_component_write(component, + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), + (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F); + + set_iir_band_coeff(component, iir_idx, band_idx, coeff[0]); + set_iir_band_coeff(component, iir_idx, band_idx, coeff[1]); + set_iir_band_coeff(component, iir_idx, band_idx, coeff[2]); + set_iir_band_coeff(component, iir_idx, band_idx, coeff[3]); + set_iir_band_coeff(component, iir_idx, band_idx, coeff[4]); + + return 0; +} + +static int wcd_iir_filter_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *ucontrol) +{ + struct wcd_iir_filter_ctl *ctl = + (struct wcd_iir_filter_ctl *)kcontrol->private_value; + struct soc_bytes_ext *params = &ctl->bytes_ext; + + ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; + ucontrol->count = params->max; + + return 0; +} + static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = { SOC_SINGLE_S8_TLV("RX1 Digital Volume", LPASS_CDC_RX1_VOL_CTL_B2_CTL, -128, 127, digital_gain), @@ -322,6 +514,44 @@ static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = { SOC_SINGLE("RX1 Mute Switch", LPASS_CDC_RX1_B6_CTL, 0, 1, 0), SOC_SINGLE("RX2 Mute Switch", LPASS_CDC_RX2_B6_CTL, 0, 1, 0), SOC_SINGLE("RX3 Mute Switch", LPASS_CDC_RX3_B6_CTL, 0, 1, 0), + + SOC_SINGLE("IIR1 Band1 Switch", LPASS_CDC_IIR1_CTL, 0, 1, 0), + SOC_SINGLE("IIR1 Band2 Switch", LPASS_CDC_IIR1_CTL, 1, 1, 0), + SOC_SINGLE("IIR1 Band3 Switch", LPASS_CDC_IIR1_CTL, 2, 1, 0), + SOC_SINGLE("IIR1 Band4 Switch", LPASS_CDC_IIR1_CTL, 3, 1, 0), + SOC_SINGLE("IIR1 Band5 Switch", LPASS_CDC_IIR1_CTL, 4, 1, 0), + SOC_SINGLE("IIR2 Band1 Switch", LPASS_CDC_IIR2_CTL, 0, 1, 0), + SOC_SINGLE("IIR2 Band2 Switch", LPASS_CDC_IIR2_CTL, 1, 1, 0), + SOC_SINGLE("IIR2 Band3 Switch", LPASS_CDC_IIR2_CTL, 2, 1, 0), + SOC_SINGLE("IIR2 Band4 Switch", LPASS_CDC_IIR2_CTL, 3, 1, 0), + SOC_SINGLE("IIR2 Band5 Switch", LPASS_CDC_IIR2_CTL, 4, 1, 0), + WCD_IIR_FILTER_CTL("IIR1 Band1", IIR1, BAND1), + WCD_IIR_FILTER_CTL("IIR1 Band2", IIR1, BAND2), + WCD_IIR_FILTER_CTL("IIR1 Band3", IIR1, BAND3), + WCD_IIR_FILTER_CTL("IIR1 Band4", IIR1, BAND4), + WCD_IIR_FILTER_CTL("IIR1 Band5", IIR1, BAND5), + WCD_IIR_FILTER_CTL("IIR2 Band1", IIR2, BAND1), + WCD_IIR_FILTER_CTL("IIR2 Band2", IIR2, BAND2), + WCD_IIR_FILTER_CTL("IIR2 Band3", IIR2, BAND3), + WCD_IIR_FILTER_CTL("IIR2 Band4", IIR2, BAND4), + WCD_IIR_FILTER_CTL("IIR2 Band5", IIR2, BAND5), + SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", LPASS_CDC_IIR1_GAIN_B1_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", LPASS_CDC_IIR1_GAIN_B2_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", LPASS_CDC_IIR1_GAIN_B3_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("IIR1 INP4 Volume", LPASS_CDC_IIR1_GAIN_B4_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("IIR2 INP1 Volume", LPASS_CDC_IIR2_GAIN_B1_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("IIR2 INP2 Volume", LPASS_CDC_IIR2_GAIN_B2_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("IIR2 INP3 Volume", LPASS_CDC_IIR2_GAIN_B3_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("IIR2 INP4 Volume", LPASS_CDC_IIR2_GAIN_B4_CTL, + 0, -84, 40, digital_gain), + }; static int msm8916_wcd_digital_enable_interpolator( @@ -448,6 +678,24 @@ static int msm8916_wcd_digital_enable_dmic(struct snd_soc_dapm_widget *w, return 0; } +static const char * const iir_inp1_text[] = { + "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3" +}; + +static const struct soc_enum iir1_inp1_mux_enum = + SOC_ENUM_SINGLE(LPASS_CDC_CONN_EQ1_B1_CTL, + 0, 6, iir_inp1_text); + +static const struct soc_enum iir2_inp1_mux_enum = + SOC_ENUM_SINGLE(LPASS_CDC_CONN_EQ2_B1_CTL, + 0, 6, iir_inp1_text); + +static const struct snd_kcontrol_new iir1_inp1_mux = + SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum); + +static const struct snd_kcontrol_new iir2_inp1_mux = + SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum); + static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = { /*RX stuff */ SND_SOC_DAPM_AIF_IN("I2S RX1", NULL, 0, SND_SOC_NOPM, 0, 0), @@ -534,6 +782,15 @@ static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = { SND_SOC_DAPM_MIC("Digital Mic1", NULL), SND_SOC_DAPM_MIC("Digital Mic2", NULL), + /* Sidetone */ + SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux), + SND_SOC_DAPM_PGA_E("IIR1", LPASS_CDC_CLK_SD_CTL, 0, 0, NULL, 0, + msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU), + + SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux), + SND_SOC_DAPM_PGA_E("IIR2", LPASS_CDC_CLK_SD_CTL, 1, 0, NULL, 0, + msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU), + }; static int msm8916_wcd_digital_get_clks(struct platform_device *pdev, @@ -708,10 +965,14 @@ static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = { {"RX1 MIX1 INP1", "RX1", "I2S RX1"}, {"RX1 MIX1 INP1", "RX2", "I2S RX2"}, {"RX1 MIX1 INP1", "RX3", "I2S RX3"}, + {"RX1 MIX1 INP1", "IIR1", "IIR1"}, + {"RX1 MIX1 INP1", "IIR2", "IIR2"}, {"RX1 MIX1 INP2", "RX1", "I2S RX1"}, {"RX1 MIX1 INP2", "RX2", "I2S RX2"}, {"RX1 MIX1 INP2", "RX3", "I2S RX3"}, + {"RX1 MIX1 INP2", "IIR1", "IIR1"}, + {"RX1 MIX1 INP2", "IIR2", "IIR2"}, {"RX1 MIX1 INP3", "RX1", "I2S RX1"}, {"RX1 MIX1 INP3", "RX2", "I2S RX2"}, @@ -728,10 +989,14 @@ static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = { {"RX2 MIX1 INP1", "RX1", "I2S RX1"}, {"RX2 MIX1 INP1", "RX2", "I2S RX2"}, {"RX2 MIX1 INP1", "RX3", "I2S RX3"}, + {"RX2 MIX1 INP1", "IIR1", "IIR1"}, + {"RX2 MIX1 INP1", "IIR2", "IIR2"}, {"RX2 MIX1 INP2", "RX1", "I2S RX1"}, {"RX2 MIX1 INP2", "RX2", "I2S RX2"}, {"RX2 MIX1 INP2", "RX3", "I2S RX3"}, + {"RX2 MIX1 INP1", "IIR1", "IIR1"}, + {"RX2 MIX1 INP1", "IIR2", "IIR2"}, {"RX2 MIX1 INP3", "RX1", "I2S RX1"}, {"RX2 MIX1 INP3", "RX2", "I2S RX2"}, @@ -748,10 +1013,27 @@ static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = { {"RX3 MIX1 INP1", "RX1", "I2S RX1"}, {"RX3 MIX1 INP1", "RX2", "I2S RX2"}, {"RX3 MIX1 INP1", "RX3", "I2S RX3"}, + {"RX3 MIX1 INP1", "IIR1", "IIR1"}, + {"RX3 MIX1 INP1", "IIR2", "IIR2"}, {"RX3 MIX1 INP2", "RX1", "I2S RX1"}, {"RX3 MIX1 INP2", "RX2", "I2S RX2"}, {"RX3 MIX1 INP2", "RX3", "I2S RX3"}, + {"RX3 MIX1 INP2", "IIR1", "IIR1"}, + {"RX3 MIX1 INP2", "IIR2", "IIR2"}, + + {"RX1 MIX2 INP1", "IIR1", "IIR1"}, + {"RX2 MIX2 INP1", "IIR1", "IIR1"}, + {"RX1 MIX2 INP1", "IIR2", "IIR2"}, + {"RX2 MIX2 INP1", "IIR2", "IIR2"}, + + {"IIR1", NULL, "IIR1 INP1 MUX"}, + {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"}, + {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"}, + + {"IIR2", NULL, "IIR2 INP1 MUX"}, + {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"}, + {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"}, {"RX3 MIX1 INP3", "RX1", "I2S RX1"}, {"RX3 MIX1 INP3", "RX2", "I2S RX2"}, From 0779935938b1b6f492f019764bc7dda77bb08ec9 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 7 Jun 2019 17:49:26 +0200 Subject: [PATCH 298/626] ASoC: Remove erroneous soc_cleanup_card_resources() call When soc_init_dai_link() call at the beginning of snd_soc_instantiate_card function fails soc_cleanup_card_resources() and then snd_soc_dapm_free() gets called with an incompletely initialized card->dapm. In particular card->dapm.card is NULL and it gets dereferenced in dapm_free_widgets(). Also dapm->list is invalid and there is an invalid pointer dereference from list_del(). The function call stack (deferred probing) on Chromebook Snow where this issue has shown up in today's -next is: snd_soc_dapm_free soc_cleanup_card_resources snd_soc_instantiate_card snd_soc_register_card devm_snd_soc_register_card snow_probe In patch 70fc53734e71 "ASoC: core: move DAI pre-links initiation to snd_soc_instantiate_card" there is an soc_cleanup_platform() call instead of soc_cleanup_card_resources() as in current -next. soc_cleanup_platform got renamed to soc_cleanup_legacy, then removed in commit adb76b5b9c47 "ASoC: soc-core: remove legacy style dai_link". It seems in merge conflict resolution the soc_cleanup_platform() call got renamed to soc_cleanup_card_resources(), instead of being removed. Correct this by removing an unnecessary soc_cleanup_card_resources() call. Fixes: a8e992342ce4 ("Merge branch 'asoc-5.2' into asoc-5.3") Reported-by: Marek Szyprowski Suggested-by: Tzung-Bi Shih Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 94a36ee8eb22..f0fa289c90d8 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1986,7 +1986,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) for_each_card_prelinks(card, i, dai_link) { ret = soc_init_dai_link(card, dai_link); if (ret) { - soc_cleanup_card_resources(card); dev_err(card->dev, "ASoC: failed to init link %s: %d\n", dai_link->name, ret); mutex_unlock(&client_mutex); From 6c0215f5d9f2a1fa5cab2ca320a41d9f19cfa80c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Jun 2019 15:54:33 -0300 Subject: [PATCH 299/626] ASoC: dt-bindings: fix some broken links from txt->yaml conversion Some new files got converted to yaml, but references weren't updated accordingly. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/media/st,stm32-dcmi.txt | 2 +- Documentation/devicetree/bindings/sound/st,stm32-i2s.txt | 2 +- Documentation/devicetree/bindings/sound/st,stm32-sai.txt | 2 +- MAINTAINERS | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmi.txt b/Documentation/devicetree/bindings/media/st,stm32-dcmi.txt index 249790a93017..3122ded82eb4 100644 --- a/Documentation/devicetree/bindings/media/st,stm32-dcmi.txt +++ b/Documentation/devicetree/bindings/media/st,stm32-dcmi.txt @@ -11,7 +11,7 @@ Required properties: - clock-names: must contain "mclk", which is the DCMI peripherial clock - pinctrl: the pincontrol settings to configure muxing properly for pins that connect to DCMI device. - See Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt. + See Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml. - dmas: phandle to DMA controller node, see Documentation/devicetree/bindings/dma/stm32-dma.txt - dma-names: must contain "tx", which is the transmit channel from DCMI to DMA diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt index 58c341300552..cbf24bcd1b8d 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt +++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt @@ -18,7 +18,7 @@ Required properties: See Documentation/devicetree/bindings/dma/stm32-dma.txt. - dma-names: Identifier for each DMA request line. Must be "tx" and "rx". - pinctrl-names: should contain only value "default" - - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt + - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml Optional properties: - resets: Reference to a reset controller asserting the reset controller diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt index 3f4467ff0aa2..944743dd9212 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt +++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt @@ -41,7 +41,7 @@ SAI subnodes required properties: "tx": if sai sub-block is configured as playback DAI "rx": if sai sub-block is configured as capture DAI - pinctrl-names: should contain only value "default" - - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt + - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml SAI subnodes Optional properties: - st,sync: specify synchronization mode. diff --git a/MAINTAINERS b/MAINTAINERS index 5cfbea4ce575..b3d686fba562 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1288,7 +1288,7 @@ ARM PRIMECELL SSP PL022 SPI DRIVER M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: Documentation/devicetree/bindings/spi/spi_pl022.txt +F: Documentation/devicetree/bindings/spi/spi-pl022.yaml F: drivers/spi/spi-pl022.c ARM PRIMECELL UART PL010 AND PL011 DRIVERS From 960f428ca0a04a59e74639571126245a3efc4bcf Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 10 Jun 2019 14:53:44 +0200 Subject: [PATCH 300/626] ASoC: meson: axg-card: fix null pointer dereference in clean up When using modern dai_link style, we must first make sure the struct snd_soc_dai_link_component exists before accessing its members. In case of early probe deferral, some of the '.cpus' or '.codecs' may not have been allocated yet. Check this before calling of_node_put() on the structure member. Fixes: c84836d7f650 ("ASoC: meson: axg-card: use modern dai_link style") Cc: Kuninori Morimoto Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index fb03258d00ae..70bb0cbad233 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -115,9 +115,11 @@ static void axg_card_clean_references(struct axg_card *priv) if (card->dai_link) { for_each_card_prelinks(card, i, link) { - of_node_put(link->cpus->of_node); + if (link->cpus) + of_node_put(link->cpus->of_node); for_each_link_codecs(link, j, codec) - of_node_put(codec->of_node); + if (codec) + of_node_put(codec->of_node); } } From d670d44582841cdd17a6d73f6d57027f14b31302 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 1 Jun 2019 04:12:14 +0000 Subject: [PATCH 301/626] ALSA: lx6464es - Remove set but not used variables 'orun_mask, urun_mask' Fixes gcc '-Wunused-but-set-variable' warning: sound/pci/lx6464es/lx_core.c: In function 'lx_interrupt_handle_async_events': sound/pci/lx6464es/lx_core.c:990:6: warning: variable 'urun_mask' set but not used [-Wunused-but-set-variable] sound/pci/lx6464es/lx_core.c:989:6: warning: variable 'orun_mask' set but not used [-Wunused-but-set-variable] They are never used, so can be removed. Signed-off-by: YueHaibing Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx_core.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index a80684bdc30d..36116881cf52 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -1001,8 +1001,6 @@ static int lx_interrupt_handle_async_events(struct lx6464es *chip, u32 irqsrc, * Stat[8] LSB overrun * */ - u64 orun_mask; - u64 urun_mask; int eb_pending_out = (irqsrc & MASK_SYS_STATUS_EOBO) ? 1 : 0; int eb_pending_in = (irqsrc & MASK_SYS_STATUS_EOBI) ? 1 : 0; @@ -1025,9 +1023,6 @@ static int lx_interrupt_handle_async_events(struct lx6464es *chip, u32 irqsrc, *r_notified_out_pipe_mask); } - orun_mask = ((u64)stat[7] << 32) + stat[8]; - urun_mask = ((u64)stat[5] << 32) + stat[6]; - /* todo: handle xrun notification */ return err; From 2ef0b7cf161ccbdcce907e5b1bb9df4c0f6941e8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:45 +0900 Subject: [PATCH 302/626] ALSA: firewire-tascam: code refactoring for registration of isochronous channels This commit is a part of preparation to perform allocation/release of isochronous channels in pcm.hw_params/hw_free callbacks. The registration of isochronous channels is done just after allocation of isochronous resources. This commit separates the registration just before starting packet streaming. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-stream.c | 84 +++++++++++++-------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index f1657a4e0621..7cddd9ece4ee 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -195,6 +195,19 @@ static void finish_session(struct snd_tscm *tscm) TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON, ®, sizeof(reg), 0); + // Unregister channels. + reg = cpu_to_be32(0x00000000); + snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, + TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH, + ®, sizeof(reg), 0); + reg = cpu_to_be32(0x00000000); + snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, + TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN, + ®, sizeof(reg), 0); + reg = cpu_to_be32(0x00000000); + snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, + TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH, + ®, sizeof(reg), 0); } static int begin_session(struct snd_tscm *tscm) @@ -202,6 +215,30 @@ static int begin_session(struct snd_tscm *tscm) __be32 reg; int err; + // Register the isochronous channel for transmitting stream. + reg = cpu_to_be32(tscm->tx_resources.channel); + err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, + TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH, + ®, sizeof(reg), 0); + if (err < 0) + return err; + + // Unknown. + reg = cpu_to_be32(0x00000002); + err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, + TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN, + ®, sizeof(reg), 0); + if (err < 0) + return err; + + // Register the isochronous channel for receiving stream. + reg = cpu_to_be32(tscm->rx_resources.channel); + err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, + TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH, + ®, sizeof(reg), 0); + if (err < 0) + return err; + reg = cpu_to_be32(0x00000001); err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, @@ -216,7 +253,7 @@ static int begin_session(struct snd_tscm *tscm) if (err < 0) return err; - /* Set an option for unknown purpose. */ + // Set an option for unknown purpose. reg = cpu_to_be32(0x00002000); err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION, @@ -224,7 +261,7 @@ static int begin_session(struct snd_tscm *tscm) if (err < 0) return err; - /* Start multiplexing PCM samples on packets. */ + // Start multiplexing PCM samples on packets. reg = cpu_to_be32(0x00000001); return snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, @@ -234,30 +271,13 @@ static int begin_session(struct snd_tscm *tscm) static void release_resources(struct snd_tscm *tscm) { - __be32 reg; - - /* Unregister channels. */ - reg = cpu_to_be32(0x00000000); - snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, - TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH, - ®, sizeof(reg), 0); - reg = cpu_to_be32(0x00000000); - snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, - TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN, - ®, sizeof(reg), 0); - reg = cpu_to_be32(0x00000000); - snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, - TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH, - ®, sizeof(reg), 0); - - /* Release isochronous resources. */ + // Release isochronous resources. fw_iso_resources_free(&tscm->tx_resources); fw_iso_resources_free(&tscm->rx_resources); } static int keep_resources(struct snd_tscm *tscm, unsigned int rate) { - __be32 reg; int err; /* Keep resources for in-stream. */ @@ -280,30 +300,6 @@ static int keep_resources(struct snd_tscm *tscm, unsigned int rate) if (err < 0) return err; - /* Register the isochronous channel for transmitting stream. */ - reg = cpu_to_be32(tscm->tx_resources.channel); - err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, - TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH, - ®, sizeof(reg), 0); - if (err < 0) - goto error; - - /* Unknown */ - reg = cpu_to_be32(0x00000002); - err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, - TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN, - ®, sizeof(reg), 0); - if (err < 0) - goto error; - - /* Register the isochronous channel for receiving stream. */ - reg = cpu_to_be32(tscm->rx_resources.channel); - err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, - TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH, - ®, sizeof(reg), 0); - if (err < 0) - goto error; - return 0; error: release_resources(tscm); From 810b37ff294d67c75cd608184a5a834f1fc3117f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:46 +0900 Subject: [PATCH 303/626] ALSA: firewire-tascam: code refactoring for reservation of isochronous resources This commit is a part of preparation to perform allocation/release of isochronous channels in pcm.hw_params/hw_free callbacks. This commit applies minor code refactoring for a helper function to allocate isochronous resources. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-stream.c | 38 +++++++++++---------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index 7cddd9ece4ee..fc963469f6b0 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -276,34 +276,24 @@ static void release_resources(struct snd_tscm *tscm) fw_iso_resources_free(&tscm->rx_resources); } -static int keep_resources(struct snd_tscm *tscm, unsigned int rate) +static int keep_resources(struct snd_tscm *tscm, unsigned int rate, + struct amdtp_stream *stream) { + struct fw_iso_resources *resources; int err; - /* Keep resources for in-stream. */ - err = amdtp_tscm_set_parameters(&tscm->tx_stream, rate); - if (err < 0) - return err; - err = fw_iso_resources_allocate(&tscm->tx_resources, - amdtp_stream_get_max_payload(&tscm->tx_stream), - fw_parent_device(tscm->unit)->max_speed); - if (err < 0) - goto error; + if (stream == &tscm->tx_stream) + resources = &tscm->tx_resources; + else + resources = &tscm->rx_resources; - /* Keep resources for out-stream. */ - err = amdtp_tscm_set_parameters(&tscm->rx_stream, rate); - if (err < 0) - return err; - err = fw_iso_resources_allocate(&tscm->rx_resources, - amdtp_stream_get_max_payload(&tscm->rx_stream), - fw_parent_device(tscm->unit)->max_speed); + err = amdtp_tscm_set_parameters(stream, rate); if (err < 0) return err; - return 0; -error: - release_resources(tscm); - return err; + return fw_iso_resources_allocate(resources, + amdtp_stream_get_max_payload(stream), + fw_parent_device(tscm->unit)->max_speed); } int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) @@ -388,7 +378,11 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) } if (!amdtp_stream_running(&tscm->rx_stream)) { - err = keep_resources(tscm, rate); + err = keep_resources(tscm, rate, &tscm->tx_stream); + if (err < 0) + goto error; + + err = keep_resources(tscm, rate, &tscm->rx_stream); if (err < 0) goto error; From a364af2eecfa3f5927460cda18e7e84881b8392f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:47 +0900 Subject: [PATCH 304/626] ALSA: firewire-tascam: code refactoring for release of isochronous resources This commit is a part of preparation to perform allocation/release of isochronous channels in pcm.hw_params/hw_free callbacks. This commit obsoletes a helper function to release isochronous resources for both direction. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-stream.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index fc963469f6b0..6ad149274050 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -269,13 +269,6 @@ static int begin_session(struct snd_tscm *tscm) ®, sizeof(reg), 0); } -static void release_resources(struct snd_tscm *tscm) -{ - // Release isochronous resources. - fw_iso_resources_free(&tscm->tx_resources); - fw_iso_resources_free(&tscm->rx_resources); -} - static int keep_resources(struct snd_tscm *tscm, unsigned int rate, struct amdtp_stream *stream) { @@ -374,7 +367,8 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) amdtp_stream_stop(&tscm->rx_stream); amdtp_stream_stop(&tscm->tx_stream); - release_resources(tscm); + fw_iso_resources_free(&tscm->tx_resources); + fw_iso_resources_free(&tscm->rx_resources); } if (!amdtp_stream_running(&tscm->rx_stream)) { @@ -427,7 +421,9 @@ error: amdtp_stream_stop(&tscm->tx_stream); finish_session(tscm); - release_resources(tscm); + + fw_iso_resources_free(&tscm->tx_resources); + fw_iso_resources_free(&tscm->rx_resources); return err; } @@ -441,7 +437,9 @@ void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) amdtp_stream_stop(&tscm->rx_stream); finish_session(tscm); - release_resources(tscm); + + fw_iso_resources_free(&tscm->tx_resources); + fw_iso_resources_free(&tscm->rx_resources); } void snd_tscm_stream_lock_changed(struct snd_tscm *tscm) From 07b266424df51894efd6d42e6de169d229559bec Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:48 +0900 Subject: [PATCH 305/626] ALSA: firewire-tascam: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Once allocated, isochronous resources are available for packet streaming, even if the streaming is cancelled. For this reason, current implementation handles allocation of the resources and starting packet streaming at the same time. However, this brings complicated procedure to start packet streaming. This commit separates the allocation and starting. The allocation is done in pcm.hw_params callback and available till pcm.hw_free callback. Even if any XRUN occurs, pcm.prepare callback is done to restart packet streaming for allocated the resources. There are two points to stop packet streaming; in pcm.hw_params and pcm.prepare callbacks. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-pcm.c | 22 +++++-- sound/firewire/tascam/tascam-stream.c | 89 ++++++++++++++++----------- sound/firewire/tascam/tascam.h | 2 + 3 files changed, 71 insertions(+), 42 deletions(-) diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index e4cc8990e195..962ef1212ac0 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -96,12 +96,16 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&tscm->mutex); - tscm->substreams_counter++; + err = snd_tscm_stream_reserve_duplex(tscm, rate); + if (err >= 0) + ++tscm->substreams_counter; mutex_unlock(&tscm->mutex); } - return 0; + return err; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, @@ -116,12 +120,16 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&tscm->mutex); - tscm->substreams_counter++; + err = snd_tscm_stream_reserve_duplex(tscm, rate); + if (err >= 0) + ++tscm->substreams_counter; mutex_unlock(&tscm->mutex); } - return 0; + return err; } static int pcm_capture_hw_free(struct snd_pcm_substream *substream) @@ -131,9 +139,10 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&tscm->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - tscm->substreams_counter--; + --tscm->substreams_counter; snd_tscm_stream_stop_duplex(tscm); + snd_tscm_stream_release_duplex(tscm); mutex_unlock(&tscm->mutex); @@ -147,9 +156,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&tscm->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - tscm->substreams_counter--; + --tscm->substreams_counter; snd_tscm_stream_stop_duplex(tscm); + snd_tscm_stream_release_duplex(tscm); mutex_unlock(&tscm->mutex); diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index 6ad149274050..18d554d46be5 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -166,7 +166,7 @@ static int set_stream_formats(struct snd_tscm *tscm, unsigned int rate) __be32 reg; int err; - /* Set an option for unknown purpose. */ + // Set an option for unknown purpose. reg = cpu_to_be32(0x00200000); err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION, @@ -174,11 +174,7 @@ static int set_stream_formats(struct snd_tscm *tscm, unsigned int rate) if (err < 0) return err; - err = enable_data_channels(tscm); - if (err < 0) - return err; - - return set_clock(tscm, rate, INT_MAX); + return enable_data_channels(tscm); } static void finish_session(struct snd_tscm *tscm) @@ -348,38 +344,66 @@ void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) fw_iso_resources_destroy(&tscm->tx_resources); } -int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) +int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) { unsigned int curr_rate; int err; + err = snd_tscm_stream_get_rate(tscm, &curr_rate); + if (err < 0) + return err; + + if (tscm->substreams_counter == 0 || rate != curr_rate) { + amdtp_stream_stop(&tscm->rx_stream); + amdtp_stream_stop(&tscm->tx_stream); + + finish_session(tscm); + + fw_iso_resources_free(&tscm->tx_resources); + fw_iso_resources_free(&tscm->rx_resources); + + err = set_clock(tscm, rate, INT_MAX); + if (err < 0) + return err; + + err = keep_resources(tscm, rate, &tscm->tx_stream); + if (err < 0) + return err; + + err = keep_resources(tscm, rate, &tscm->rx_stream); + if (err < 0) { + fw_iso_resources_free(&tscm->tx_resources); + return err; + } + } + + return 0; +} + +void snd_tscm_stream_release_duplex(struct snd_tscm *tscm) +{ + if (tscm->substreams_counter == 0) { + fw_iso_resources_free(&tscm->tx_resources); + fw_iso_resources_free(&tscm->rx_resources); + } +} + +int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) +{ + int err; + if (tscm->substreams_counter == 0) return 0; - err = snd_tscm_stream_get_rate(tscm, &curr_rate); - if (err < 0) - return err; - if (curr_rate != rate || - amdtp_streaming_error(&tscm->rx_stream) || + if (amdtp_streaming_error(&tscm->rx_stream) || amdtp_streaming_error(&tscm->tx_stream)) { - finish_session(tscm); - amdtp_stream_stop(&tscm->rx_stream); amdtp_stream_stop(&tscm->tx_stream); - fw_iso_resources_free(&tscm->tx_resources); - fw_iso_resources_free(&tscm->rx_resources); + finish_session(tscm); } if (!amdtp_stream_running(&tscm->rx_stream)) { - err = keep_resources(tscm, rate, &tscm->tx_stream); - if (err < 0) - goto error; - - err = keep_resources(tscm, rate, &tscm->rx_stream); - if (err < 0) - goto error; - err = set_stream_formats(tscm, rate); if (err < 0) goto error; @@ -422,24 +446,17 @@ error: finish_session(tscm); - fw_iso_resources_free(&tscm->tx_resources); - fw_iso_resources_free(&tscm->rx_resources); - return err; } void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) { - if (tscm->substreams_counter > 0) - return; + if (tscm->substreams_counter == 0) { + amdtp_stream_stop(&tscm->tx_stream); + amdtp_stream_stop(&tscm->rx_stream); - amdtp_stream_stop(&tscm->tx_stream); - amdtp_stream_stop(&tscm->rx_stream); - - finish_session(tscm); - - fw_iso_resources_free(&tscm->tx_resources); - fw_iso_resources_free(&tscm->rx_resources); + finish_session(tscm); + } } void snd_tscm_stream_lock_changed(struct snd_tscm *tscm) diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 6a411ee0dcf1..1cb75c374f11 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -147,6 +147,8 @@ int snd_tscm_stream_get_clock(struct snd_tscm *tscm, int snd_tscm_stream_init_duplex(struct snd_tscm *tscm); void snd_tscm_stream_update_duplex(struct snd_tscm *tscm); void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm); +int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate); +void snd_tscm_stream_release_duplex(struct snd_tscm *tscm); int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate); void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm); From a0c049a647fbf55e8e6338a5c1e9316f6fbeabb2 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:49 +0900 Subject: [PATCH 306/626] ALSA: firewire-tascam: update isochronous resources when starting packet streaming after bus reset After bus reset, isochronous resource manager releases all of allocated isochronous resources. The nodes to restart packet streaming should request reallocation of the resources. However, between the bus-reset and invocation of 'struct fw_driver.update' handler, ALSA PCM application can detect this situation by XRUN because the target device cancelled to transmit packets once bus-reset occurs. Due to the above mechanism, ALSA firewire-tascam driver just stops packet streaming in the update handler, thus pcm.prepare handler should request the reallocation. This commit requests the reallocation in pcm.prepare callback when bus generation is changed. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-stream.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index 18d554d46be5..be9dcc808188 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -321,7 +321,7 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) return err; } -/* At bus reset, streaming is stopped and some registers are clear. */ +// At bus reset, streaming is stopped and some registers are clear. void snd_tscm_stream_update_duplex(struct snd_tscm *tscm) { amdtp_stream_pcm_abort(&tscm->tx_stream); @@ -390,6 +390,7 @@ void snd_tscm_stream_release_duplex(struct snd_tscm *tscm) int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) { + unsigned int generation = tscm->rx_resources.generation; int err; if (tscm->substreams_counter == 0) @@ -403,6 +404,16 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) finish_session(tscm); } + if (generation != fw_parent_device(tscm->unit)->card->generation) { + err = fw_iso_resources_update(&tscm->tx_resources); + if (err < 0) + goto error; + + err = fw_iso_resources_update(&tscm->rx_resources); + if (err < 0) + goto error; + } + if (!amdtp_stream_running(&tscm->rx_stream)) { err = set_stream_formats(tscm, rate); if (err < 0) From ece92831f0fa49f6b7bab0843c096293eab1b113 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:50 +0900 Subject: [PATCH 307/626] ALSA: firewire-tascam: minor code refactoring to finish streaming session The operation to finish packet streaming corresponds to stopping isochronous contexts. This commit applies code refactoring to move codes to stop into a helper function to finish the session. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-stream.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index be9dcc808188..f572dfc15114 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -181,6 +181,9 @@ static void finish_session(struct snd_tscm *tscm) { __be32 reg; + amdtp_stream_stop(&tscm->rx_stream); + amdtp_stream_stop(&tscm->tx_stream); + reg = 0; snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, @@ -354,9 +357,6 @@ int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) return err; if (tscm->substreams_counter == 0 || rate != curr_rate) { - amdtp_stream_stop(&tscm->rx_stream); - amdtp_stream_stop(&tscm->tx_stream); - finish_session(tscm); fw_iso_resources_free(&tscm->tx_resources); @@ -397,12 +397,8 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) return 0; if (amdtp_streaming_error(&tscm->rx_stream) || - amdtp_streaming_error(&tscm->tx_stream)) { - amdtp_stream_stop(&tscm->rx_stream); - amdtp_stream_stop(&tscm->tx_stream); - + amdtp_streaming_error(&tscm->tx_stream)) finish_session(tscm); - } if (generation != fw_parent_device(tscm->unit)->card->generation) { err = fw_iso_resources_update(&tscm->tx_resources); @@ -452,9 +448,6 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) return 0; error: - amdtp_stream_stop(&tscm->rx_stream); - amdtp_stream_stop(&tscm->tx_stream); - finish_session(tscm); return err; @@ -462,12 +455,8 @@ error: void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) { - if (tscm->substreams_counter == 0) { - amdtp_stream_stop(&tscm->tx_stream); - amdtp_stream_stop(&tscm->rx_stream); - + if (tscm->substreams_counter == 0) finish_session(tscm); - } } void snd_tscm_stream_lock_changed(struct snd_tscm *tscm) From d8f291b7b84c4d5eb7a250a4f56cc44ed5bef3cf Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:51 +0900 Subject: [PATCH 308/626] ALSA: firewire-tascam: code refactoring for pcm.hw_params/hw_free callbacks The pairs of pcm.hw_params callbacks and .hw_free callbacks for both direction have no differences. This commit unifies the pairs. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-pcm.c | 55 ++++-------------------------- 1 file changed, 7 insertions(+), 48 deletions(-) diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 962ef1212ac0..450711bef508 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -84,8 +84,8 @@ static int pcm_close(struct snd_pcm_substream *substream) return 0; } -static int pcm_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_tscm *tscm = substream->private_data; int err; @@ -108,48 +108,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, return err; } -static int pcm_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_tscm *tscm = substream->private_data; - int err; - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { - unsigned int rate = params_rate(hw_params); - - mutex_lock(&tscm->mutex); - err = snd_tscm_stream_reserve_duplex(tscm, rate); - if (err >= 0) - ++tscm->substreams_counter; - mutex_unlock(&tscm->mutex); - } - - return err; -} - -static int pcm_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_tscm *tscm = substream->private_data; - - mutex_lock(&tscm->mutex); - - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - --tscm->substreams_counter; - - snd_tscm_stream_stop_duplex(tscm); - snd_tscm_stream_release_duplex(tscm); - - mutex_unlock(&tscm->mutex); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static int pcm_playback_hw_free(struct snd_pcm_substream *substream) +static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_tscm *tscm = substream->private_data; @@ -270,8 +229,8 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_capture_hw_params, - .hw_free = pcm_capture_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, @@ -282,8 +241,8 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_playback_hw_params, - .hw_free = pcm_playback_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, From 47b87c8ed072b6d0fd54f1751ad0184e7c8e20e5 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:52 +0900 Subject: [PATCH 309/626] ALSA: fireface: add protocol-specific operation to allocate isochronous resources This commit is a part of preparation to perform allocation/release of isochronous channels in pcm.hw_params/hw_free callbacks. In ALSA fireface driver, the allocation of isochronous resources is programmed in each implementation of protocol. This commit adds protocol-specific operation for the allocation separated from the operation to begin session. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-stream.c | 4 ++++ sound/firewire/fireface/ff.h | 1 + 2 files changed, 5 insertions(+) diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index a8a90f1ae09e..740963e4e1c9 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -156,6 +156,10 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) if (err < 0) return err; + err = ff->spec->protocol->allocate_resources(ff, rate); + if (err < 0) + goto error; + err = ff->spec->protocol->begin_session(ff, rate); if (err < 0) goto error; diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index ed8fea0ff5e1..c478103388a2 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -113,6 +113,7 @@ struct snd_ff_protocol { int (*get_clock)(struct snd_ff *ff, unsigned int *rate, enum snd_ff_clock_src *src); int (*switch_fetching_mode)(struct snd_ff *ff, bool enable); + int (*allocate_resources)(struct snd_ff *ff, unsigned int rate); int (*begin_session)(struct snd_ff *ff, unsigned int rate); void (*finish_session)(struct snd_ff *ff); void (*dump_status)(struct snd_ff *ff, struct snd_info_buffer *buffer); From ca8159a8e66fc78328d522f0d84d0518695d1290 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:53 +0900 Subject: [PATCH 310/626] ALSA: fireface: support allocate_resources operation in ff800 protocol This commit is a part of preparation to perform allocation/release of isochronous channels in pcm.hw_params/hw_free callbacks. This commit implements allocate_resources callback for ff800 protocol. As I noted in commit fc716397a5c7 ("ALSA: fireface: add support for packet streaming on Fireface 800"), this unit allocates isochronous resources for tx stream voluntarily. Therefore, this commit is to maintain isochronous rsources for rx stream. In the callback, sampling transfer frequency is configured to the device as well. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-protocol-former.c | 46 ++++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c index 8d1c2c6e907b..11575d17d6cc 100644 --- a/sound/firewire/fireface/ff-protocol-former.c +++ b/sound/firewire/fireface/ff-protocol-former.c @@ -293,27 +293,6 @@ static int former_fill_midi_msg(struct snd_ff *ff, #define FF800_TX_PACKET_ISOC_CH 0x0000801c0008 -static int allocate_rx_resources(struct snd_ff *ff) -{ - u32 data; - __le32 reg; - int err; - - // Controllers should allocate isochronous resources for rx stream. - err = fw_iso_resources_allocate(&ff->rx_resources, - amdtp_stream_get_max_payload(&ff->rx_stream), - fw_parent_device(ff->unit)->max_speed); - if (err < 0) - return err; - - // Set isochronous channel and the number of quadlets of rx packets. - data = ff->rx_stream.data_block_quadlets << 3; - data = (data << 8) | ff->rx_resources.channel; - reg = cpu_to_le32(data); - return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, - FF800_RX_PACKET_FORMAT, ®, sizeof(reg), 0); -} - static int allocate_tx_resources(struct snd_ff *ff) { __le32 reg; @@ -355,8 +334,9 @@ static int allocate_tx_resources(struct snd_ff *ff) return 0; } -static int ff800_begin_session(struct snd_ff *ff, unsigned int rate) +static int ff800_allocate_resources(struct snd_ff *ff, unsigned int rate) { + u32 data; __le32 reg; int err; @@ -371,14 +351,31 @@ static int ff800_begin_session(struct snd_ff *ff, unsigned int rate) // Let's sleep for a bit. msleep(100); - err = allocate_rx_resources(ff); + // Controllers should allocate isochronous resources for rx stream. + err = fw_iso_resources_allocate(&ff->rx_resources, + amdtp_stream_get_max_payload(&ff->rx_stream), + fw_parent_device(ff->unit)->max_speed); if (err < 0) return err; - err = allocate_tx_resources(ff); + // Set isochronous channel and the number of quadlets of rx packets. + // This should be done before the allocation of tx resources to avoid + // periodical noise. + data = ff->rx_stream.data_block_quadlets << 3; + data = (data << 8) | ff->rx_resources.channel; + reg = cpu_to_le32(data); + err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, + FF800_RX_PACKET_FORMAT, ®, sizeof(reg), 0); if (err < 0) return err; + return allocate_tx_resources(ff); +} + +static int ff800_begin_session(struct snd_ff *ff, unsigned int rate) +{ + __le32 reg; + reg = cpu_to_le32(0x80000000); reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets); if (fw_parent_device(ff->unit)->max_speed == SCODE_800) @@ -420,6 +417,7 @@ const struct snd_ff_protocol snd_ff_protocol_ff800 = { .fill_midi_msg = former_fill_midi_msg, .get_clock = former_get_clock, .switch_fetching_mode = former_switch_fetching_mode, + .allocate_resources = ff800_allocate_resources, .begin_session = ff800_begin_session, .finish_session = ff800_finish_session, .dump_status = former_dump_status, From 75be43d97f55977ef34e2d59968a79aad8337199 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:54 +0900 Subject: [PATCH 311/626] ALSA: fireface: support allocate_resources operation in ff400 protocol This commit is a part of preparation to perform allocation/release of isochronous channels in pcm.hw_params/hw_free callbacks. This commit implements allocate_resources callback for ff400 protocol. In this callback, sampling transfer frequency is configured to the device as well. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-protocol-former.c | 36 +++++++++----------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c index 11575d17d6cc..0517eb718f54 100644 --- a/sound/firewire/fireface/ff-protocol-former.c +++ b/sound/firewire/fireface/ff-protocol-former.c @@ -429,12 +429,11 @@ const struct snd_ff_protocol snd_ff_protocol_ff800 = { #define FF400_TX_PACKET_FORMAT 0x00008010050cull #define FF400_ISOC_COMM_STOP 0x000080100510ull -/* - * Fireface 400 manages isochronous channel number in 3 bit field. Therefore, - * we can allocate between 0 and 7 channel. - */ -static int keep_resources(struct snd_ff *ff, unsigned int rate) +// Fireface 400 manages isochronous channel number in 3 bit field. Therefore, +// we can allocate between 0 and 7 channel. +static int ff400_allocate_resources(struct snd_ff *ff, unsigned int rate) { + __le32 reg; enum snd_ff_stream_mode mode; int i; int err; @@ -447,11 +446,20 @@ static int keep_resources(struct snd_ff *ff, unsigned int rate) if (i >= CIP_SFC_COUNT) return -EINVAL; + // Set the number of data blocks transferred in a second. + reg = cpu_to_le32(rate); + err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, + FF400_STF, ®, sizeof(reg), 0); + if (err < 0) + return err; + + msleep(100); + err = snd_ff_stream_get_multiplier_mode(i, &mode); if (err < 0) return err; - /* Keep resources for in-stream. */ + // Keep resources for in-stream. ff->tx_resources.channels_mask = 0x00000000000000ffuLL; err = fw_iso_resources_allocate(&ff->tx_resources, amdtp_stream_get_max_payload(&ff->tx_stream), @@ -459,7 +467,7 @@ static int keep_resources(struct snd_ff *ff, unsigned int rate) if (err < 0) return err; - /* Keep resources for out-stream. */ + // Keep resources for out-stream. ff->rx_resources.channels_mask = 0x00000000000000ffuLL; err = fw_iso_resources_allocate(&ff->rx_resources, amdtp_stream_get_max_payload(&ff->rx_stream), @@ -475,19 +483,6 @@ static int ff400_begin_session(struct snd_ff *ff, unsigned int rate) __le32 reg; int err; - err = keep_resources(ff, rate); - if (err < 0) - return err; - - /* Set the number of data blocks transferred in a second. */ - reg = cpu_to_le32(rate); - err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, - FF400_STF, ®, sizeof(reg), 0); - if (err < 0) - return err; - - msleep(100); - /* * Set isochronous channel and the number of quadlets of received * packets. @@ -589,6 +584,7 @@ const struct snd_ff_protocol snd_ff_protocol_ff400 = { .fill_midi_msg = former_fill_midi_msg, .get_clock = former_get_clock, .switch_fetching_mode = former_switch_fetching_mode, + .allocate_resources = ff400_allocate_resources, .begin_session = ff400_begin_session, .finish_session = ff400_finish_session, .dump_status = former_dump_status, From 60aec494b389ae518b9fe8812bce953440c33123 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:55 +0900 Subject: [PATCH 312/626] ALSA: fireface: support allocate_resources operation in latter protocol This commit is a part of preparation to perform allocation/release of isochronous channels in pcm.hw_params/hw_free callbacks. This commit implements allocate_resources callback for the protocol specific to latter models. The encoded values of constant table is split into several condition statements to separate the operation to configure sampling transfer frequency from the operation to configure the number of data channels in rx packet. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-protocol-latter.c | 123 +++++++++---------- 1 file changed, 61 insertions(+), 62 deletions(-) diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c index c8236ff89b7f..3d12ba5b2a9b 100644 --- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -97,75 +97,31 @@ static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable) LATTER_FETCH_MODE, ®, sizeof(reg), 0); } -static int keep_resources(struct snd_ff *ff, unsigned int rate) +static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate) { enum snd_ff_stream_mode mode; - int i; - int err; - - // Check whether the given value is supported or not. - for (i = 0; i < CIP_SFC_COUNT; i++) { - if (amdtp_rate_table[i] == rate) - break; - } - if (i >= CIP_SFC_COUNT) - return -EINVAL; - - err = snd_ff_stream_get_multiplier_mode(i, &mode); - if (err < 0) - return err; - - /* Keep resources for in-stream. */ - ff->tx_resources.channels_mask = 0x00000000000000ffuLL; - err = fw_iso_resources_allocate(&ff->tx_resources, - amdtp_stream_get_max_payload(&ff->tx_stream), - fw_parent_device(ff->unit)->max_speed); - if (err < 0) - return err; - - /* Keep resources for out-stream. */ - ff->rx_resources.channels_mask = 0x00000000000000ffuLL; - err = fw_iso_resources_allocate(&ff->rx_resources, - amdtp_stream_get_max_payload(&ff->rx_stream), - fw_parent_device(ff->unit)->max_speed); - if (err < 0) - fw_iso_resources_free(&ff->tx_resources); - - return err; -} - -static int latter_begin_session(struct snd_ff *ff, unsigned int rate) -{ - static const struct { - unsigned int stf; - unsigned int code; - unsigned int flag; - } *entry, rate_table[] = { - { 32000, 0x00, 0x92, }, - { 44100, 0x02, 0x92, }, - { 48000, 0x04, 0x92, }, - { 64000, 0x08, 0x8e, }, - { 88200, 0x0a, 0x8e, }, - { 96000, 0x0c, 0x8e, }, - { 128000, 0x10, 0x8c, }, - { 176400, 0x12, 0x8c, }, - { 192000, 0x14, 0x8c, }, - }; - u32 data; + unsigned int code; __le32 reg; unsigned int count; int i; int err; - for (i = 0; i < ARRAY_SIZE(rate_table); ++i) { - entry = rate_table + i; - if (entry->stf == rate) - break; - } - if (i == ARRAY_SIZE(rate_table)) + // Set the number of data blocks transferred in a second. + if (rate % 32000 == 0) + code = 0x00; + else if (rate % 44100 == 0) + code = 0x02; + else if (rate % 48000 == 0) + code = 0x04; + else return -EINVAL; - reg = cpu_to_le32(entry->code); + if (rate >= 64000 && rate < 128000) + code |= 0x08; + else if (rate >= 128000 && rate < 192000) + code |= 0x10; + + reg = cpu_to_le32(code); err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, LATTER_STF, ®, sizeof(reg), 0); if (err < 0) @@ -187,10 +143,52 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate) if (count == 10) return -ETIMEDOUT; - err = keep_resources(ff, rate); + for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); ++i) { + if (rate == amdtp_rate_table[i]) + break; + } + if (i == ARRAY_SIZE(amdtp_rate_table)) + return -EINVAL; + + err = snd_ff_stream_get_multiplier_mode(i, &mode); if (err < 0) return err; + // Keep resources for in-stream. + ff->tx_resources.channels_mask = 0x00000000000000ffuLL; + err = fw_iso_resources_allocate(&ff->tx_resources, + amdtp_stream_get_max_payload(&ff->tx_stream), + fw_parent_device(ff->unit)->max_speed); + if (err < 0) + return err; + + // Keep resources for out-stream. + ff->rx_resources.channels_mask = 0x00000000000000ffuLL; + err = fw_iso_resources_allocate(&ff->rx_resources, + amdtp_stream_get_max_payload(&ff->rx_stream), + fw_parent_device(ff->unit)->max_speed); + if (err < 0) + fw_iso_resources_free(&ff->tx_resources); + + return err; +} + +static int latter_begin_session(struct snd_ff *ff, unsigned int rate) +{ + unsigned int flag; + u32 data; + __le32 reg; + int err; + + if (rate >= 32000 && rate <= 48000) + flag = 0x92; + else if (rate >= 64000 && rate <= 96000) + flag = 0x8e; + else if (rate >= 128000 && rate <= 192000) + flag = 0x8c; + else + return -EINVAL; + data = (ff->tx_resources.channel << 8) | ff->rx_resources.channel; reg = cpu_to_le32(data); err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, @@ -200,7 +198,7 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate) // Always use the maximum number of data channels in data block of // packet. - reg = cpu_to_le32(entry->flag); + reg = cpu_to_le32(flag); return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, LATTER_ISOC_START, ®, sizeof(reg), 0); } @@ -424,6 +422,7 @@ const struct snd_ff_protocol snd_ff_protocol_latter = { .fill_midi_msg = latter_fill_midi_msg, .get_clock = latter_get_clock, .switch_fetching_mode = latter_switch_fetching_mode, + .allocate_resources = latter_allocate_resources, .begin_session = latter_begin_session, .finish_session = latter_finish_session, .dump_status = latter_dump_status, From 55162d2bb0e86b2d0f87a82713b1e7ee761bf8a8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:56 +0900 Subject: [PATCH 313/626] ALSA: fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Once allocated, isochronous resources are available for packet streaming, even if the streaming is cancelled. For this reason, current implementation handles allocation of the resources and starting packet streaming at the same time. However, this brings complicated procedure to start packet streaming. This commit separates the allocation and starting. The allocation is done in pcm.hw_params callback and available till pcm.hw_free callback. Even if any XRUN occurs, pcm.prepare callback is done to restart packet streaming for allocated the resources. There are two points to stop packet streaming; in pcm.hw_params and pcm.prepare callbacks. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-pcm.c | 18 ++++++-- sound/firewire/fireface/ff-stream.c | 67 ++++++++++++++++++----------- sound/firewire/fireface/ff.h | 2 + 3 files changed, 57 insertions(+), 30 deletions(-) diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index 5adf04b95c04..53477404a58f 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -211,8 +211,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&ff->mutex); - ff->substreams_counter++; + err = snd_ff_stream_reserve_duplex(ff, rate); + if (err >= 0) + ++ff->substreams_counter; mutex_unlock(&ff->mutex); } @@ -231,8 +235,12 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&ff->mutex); - ff->substreams_counter++; + err = snd_ff_stream_reserve_duplex(ff, rate); + if (err >= 0) + ++ff->substreams_counter; mutex_unlock(&ff->mutex); } @@ -246,9 +254,10 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&ff->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - ff->substreams_counter--; + --ff->substreams_counter; snd_ff_stream_stop_duplex(ff); + snd_ff_stream_release_duplex(ff); mutex_unlock(&ff->mutex); @@ -262,9 +271,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&ff->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - ff->substreams_counter--; + --ff->substreams_counter; snd_ff_stream_stop_duplex(ff); + snd_ff_stream_release_duplex(ff); mutex_unlock(&ff->mutex); diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 740963e4e1c9..d9d1b469a8e9 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -31,12 +31,6 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, return 0; } -static void release_resources(struct snd_ff *ff) -{ - fw_iso_resources_free(&ff->tx_resources); - fw_iso_resources_free(&ff->rx_resources); -} - static inline void finish_session(struct snd_ff *ff) { ff->spec->protocol->finish_session(ff); @@ -104,36 +98,27 @@ void snd_ff_stream_destroy_duplex(struct snd_ff *ff) destroy_stream(ff, AMDTP_OUT_STREAM); } -int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) +int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate) { unsigned int curr_rate; enum snd_ff_clock_src src; int err; - if (ff->substreams_counter == 0) - return 0; - err = ff->spec->protocol->get_clock(ff, &curr_rate, &src); if (err < 0) return err; - if (curr_rate != rate || - amdtp_streaming_error(&ff->tx_stream) || - amdtp_streaming_error(&ff->rx_stream)) { - finish_session(ff); + + if (ff->substreams_counter == 0 || curr_rate != rate) { + enum snd_ff_stream_mode mode; + int i; amdtp_stream_stop(&ff->tx_stream); amdtp_stream_stop(&ff->rx_stream); - release_resources(ff); - } + finish_session(ff); - /* - * Regardless of current source of clock signal, drivers transfer some - * packets. Then, the device transfers packets. - */ - if (!amdtp_stream_running(&ff->rx_stream)) { - enum snd_ff_stream_mode mode; - int i; + fw_iso_resources_free(&ff->tx_resources); + fw_iso_resources_free(&ff->rx_resources); for (i = 0; i < CIP_SFC_COUNT; ++i) { if (amdtp_rate_table[i] == rate) @@ -158,8 +143,40 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) err = ff->spec->protocol->allocate_resources(ff, rate); if (err < 0) - goto error; + return err; + } + return 0; +} + +void snd_ff_stream_release_duplex(struct snd_ff *ff) +{ + if (ff->substreams_counter == 0) { + fw_iso_resources_free(&ff->tx_resources); + fw_iso_resources_free(&ff->rx_resources); + } +} + +int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) +{ + int err; + + if (ff->substreams_counter == 0) + return 0; + + if (amdtp_streaming_error(&ff->tx_stream) || + amdtp_streaming_error(&ff->rx_stream)) { + amdtp_stream_stop(&ff->tx_stream); + amdtp_stream_stop(&ff->rx_stream); + + finish_session(ff); + } + + /* + * Regardless of current source of clock signal, drivers transfer some + * packets. Then, the device transfers packets. + */ + if (!amdtp_stream_running(&ff->rx_stream)) { err = ff->spec->protocol->begin_session(ff, rate); if (err < 0) goto error; @@ -201,7 +218,6 @@ error: amdtp_stream_stop(&ff->rx_stream); finish_session(ff); - release_resources(ff); return err; } @@ -214,7 +230,6 @@ void snd_ff_stream_stop_duplex(struct snd_ff *ff) amdtp_stream_stop(&ff->tx_stream); amdtp_stream_stop(&ff->rx_stream); finish_session(ff); - release_resources(ff); } void snd_ff_stream_update_duplex(struct snd_ff *ff) diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index c478103388a2..fe5739ee1c88 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -138,6 +138,8 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, enum snd_ff_stream_mode *mode); int snd_ff_stream_init_duplex(struct snd_ff *ff); void snd_ff_stream_destroy_duplex(struct snd_ff *ff); +int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate); +void snd_ff_stream_release_duplex(struct snd_ff *ff); int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate); void snd_ff_stream_stop_duplex(struct snd_ff *ff); void snd_ff_stream_update_duplex(struct snd_ff *ff); From b88f4d7c3812e3f3f746895cc4475b02c530303e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:57 +0900 Subject: [PATCH 314/626] ALSA: fireface: update isochronous resources when starting packet streaming after bus-reset After bus reset, isochronous resource manager releases all of allocated isochronous resources. The nodes to restart packet streaming should request reallocation of the resources. However, between the bus-reset and invocation of 'struct fw_driver.update' handler, ALSA PCM application can detect this situation by XRUN because the target device cancelled to transmit packets once bus-reset occurs. Due to the above mechanism, ALSA fireface driver just stops packet streaming in the update handler, thus pcm.prepare handler should request the reallocation. This commit requests the reallocation in pcm.prepare callback when bus generation is changed. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-protocol-former.c | 34 ++++++++++++++------ sound/firewire/fireface/ff-protocol-latter.c | 11 +++++++ sound/firewire/fireface/ff-stream.c | 5 +-- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c index 0517eb718f54..bf44cad7985e 100644 --- a/sound/firewire/fireface/ff-protocol-former.c +++ b/sound/firewire/fireface/ff-protocol-former.c @@ -374,8 +374,15 @@ static int ff800_allocate_resources(struct snd_ff *ff, unsigned int rate) static int ff800_begin_session(struct snd_ff *ff, unsigned int rate) { + unsigned int generation = ff->rx_resources.generation; __le32 reg; + if (generation != fw_parent_device(ff->unit)->card->generation) { + int err = fw_iso_resources_update(&ff->rx_resources); + if (err < 0) + return err; + } + reg = cpu_to_le32(0x80000000); reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets); if (fw_parent_device(ff->unit)->max_speed == SCODE_800) @@ -480,13 +487,22 @@ static int ff400_allocate_resources(struct snd_ff *ff, unsigned int rate) static int ff400_begin_session(struct snd_ff *ff, unsigned int rate) { + unsigned int generation = ff->rx_resources.generation; __le32 reg; int err; - /* - * Set isochronous channel and the number of quadlets of received - * packets. - */ + if (generation != fw_parent_device(ff->unit)->card->generation) { + err = fw_iso_resources_update(&ff->tx_resources); + if (err < 0) + return err; + + err = fw_iso_resources_update(&ff->rx_resources); + if (err < 0) + return err; + } + + // Set isochronous channel and the number of quadlets of received + // packets. reg = cpu_to_le32(((ff->rx_stream.data_block_quadlets << 3) << 8) | ff->rx_resources.channel); err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, @@ -494,11 +510,9 @@ static int ff400_begin_session(struct snd_ff *ff, unsigned int rate) if (err < 0) return err; - /* - * Set isochronous channel and the number of quadlets of transmitted - * packet. - */ - /* TODO: investigate the purpose of this 0x80. */ + // Set isochronous channel and the number of quadlets of transmitted + // packet. + // TODO: investigate the purpose of this 0x80. reg = cpu_to_le32((0x80 << 24) | (ff->tx_resources.channel << 5) | (ff->tx_stream.data_block_quadlets)); @@ -507,7 +521,7 @@ static int ff400_begin_session(struct snd_ff *ff, unsigned int rate) if (err < 0) return err; - /* Allow to transmit packets. */ + // Allow to transmit packets. reg = cpu_to_le32(0x00000001); return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, FF400_ISOC_COMM_START, ®, sizeof(reg), 0); diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c index 3d12ba5b2a9b..8d6ebb638e93 100644 --- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -175,6 +175,7 @@ static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate) static int latter_begin_session(struct snd_ff *ff, unsigned int rate) { + unsigned int generation = ff->rx_resources.generation; unsigned int flag; u32 data; __le32 reg; @@ -189,6 +190,16 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate) else return -EINVAL; + if (generation != fw_parent_device(ff->unit)->card->generation) { + err = fw_iso_resources_update(&ff->tx_resources); + if (err < 0) + return err; + + err = fw_iso_resources_update(&ff->rx_resources); + if (err < 0) + return err; + } + data = (ff->tx_resources.channel << 8) | ff->rx_resources.channel; reg = cpu_to_le32(data); err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index d9d1b469a8e9..4f40dfb11979 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -234,15 +234,12 @@ void snd_ff_stream_stop_duplex(struct snd_ff *ff) void snd_ff_stream_update_duplex(struct snd_ff *ff) { - /* The device discontinue to transfer packets. */ + // The device discontinue to transfer packets. amdtp_stream_pcm_abort(&ff->tx_stream); amdtp_stream_stop(&ff->tx_stream); amdtp_stream_pcm_abort(&ff->rx_stream); amdtp_stream_stop(&ff->rx_stream); - - fw_iso_resources_update(&ff->tx_resources); - fw_iso_resources_update(&ff->rx_resources); } void snd_ff_stream_lock_changed(struct snd_ff *ff) From f55e2a897962a55e15cc881ee86ee23f4817dffd Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:58 +0900 Subject: [PATCH 315/626] ALSA: fireface: minor code refactoring to finish streaming session The operation to finish packet streaming corresponds to stopping isochronous contexts. This commit applies code refactoring to move codes to stop into a helper function to finish the session. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-stream.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 4f40dfb11979..884705ecf940 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -33,6 +33,9 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, static inline void finish_session(struct snd_ff *ff) { + amdtp_stream_stop(&ff->tx_stream); + amdtp_stream_stop(&ff->rx_stream); + ff->spec->protocol->finish_session(ff); ff->spec->protocol->switch_fetching_mode(ff, false); } @@ -112,9 +115,6 @@ int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate) enum snd_ff_stream_mode mode; int i; - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_stop(&ff->rx_stream); - finish_session(ff); fw_iso_resources_free(&ff->tx_resources); @@ -165,12 +165,8 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) return 0; if (amdtp_streaming_error(&ff->tx_stream) || - amdtp_streaming_error(&ff->rx_stream)) { - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_stop(&ff->rx_stream); - + amdtp_streaming_error(&ff->rx_stream)) finish_session(ff); - } /* * Regardless of current source of clock signal, drivers transfer some @@ -214,9 +210,6 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) return 0; error: - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_stop(&ff->rx_stream); - finish_session(ff); return err; @@ -224,12 +217,8 @@ error: void snd_ff_stream_stop_duplex(struct snd_ff *ff) { - if (ff->substreams_counter > 0) - return; - - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_stop(&ff->rx_stream); - finish_session(ff); + if (ff->substreams_counter == 0) + finish_session(ff); } void snd_ff_stream_update_duplex(struct snd_ff *ff) From 49f621fe3c798fe9361e7a303783d091cbb551f9 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 2 Jun 2019 16:12:59 +0900 Subject: [PATCH 316/626] ALSA: fireface: code refactoring for pcm.hw_params/hw_free callbacks The pairs of pcm.hw_params callbacks and .hw_free callbacks for both direction have no differences. This commit unifies the pairs. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-pcm.c | 55 ++++---------------------------- 1 file changed, 7 insertions(+), 48 deletions(-) diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index 53477404a58f..938985c2d4a8 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -199,8 +199,8 @@ static int pcm_close(struct snd_pcm_substream *substream) return 0; } -static int pcm_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_ff *ff = substream->private_data; int err; @@ -223,48 +223,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, return 0; } -static int pcm_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_ff *ff = substream->private_data; - int err; - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { - unsigned int rate = params_rate(hw_params); - - mutex_lock(&ff->mutex); - err = snd_ff_stream_reserve_duplex(ff, rate); - if (err >= 0) - ++ff->substreams_counter; - mutex_unlock(&ff->mutex); - } - - return 0; -} - -static int pcm_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_ff *ff = substream->private_data; - - mutex_lock(&ff->mutex); - - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - --ff->substreams_counter; - - snd_ff_stream_stop_duplex(ff); - snd_ff_stream_release_duplex(ff); - - mutex_unlock(&ff->mutex); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static int pcm_playback_hw_free(struct snd_pcm_substream *substream) +static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_ff *ff = substream->private_data; @@ -385,8 +344,8 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_capture_hw_params, - .hw_free = pcm_capture_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, @@ -397,8 +356,8 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_playback_hw_params, - .hw_free = pcm_playback_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, From 861bee5adc8be511a93e949a338d35974fbdf10b Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Mon, 10 Jun 2019 11:51:46 +0200 Subject: [PATCH 317/626] ALSA: usb-audio: Enable .product_name override for Emagic, Unitor 8. The Emagic Unitor 8 does not provide iManufacturer and iProduct fields in its device descriptor. These fields are used by alsa to make build the device name. Thus uncomment the .product-name in the quirks-table. Without this change the device shows up as 'USB Device 0x86a:0x01'. Output of lsusb and amidi: https://gist.github.com/ensonic/7820a102e91f31575be355da2b6b33bc Signed-off-by: Stefan Sauer Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 5600143ff660..5fd748c4eb30 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2422,7 +2422,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE(0x086a, 0x0001), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { .vendor_name = "Emagic", - /* .product_name = "Unitor8", */ + .product_name = "Unitor8", .ifnum = 2, .type = QUIRK_MIDI_EMAGIC, .data = & (const struct snd_usb_midi_endpoint_info) { From 6bc9322936f240d96b1a76d87a9f308456bf31bf Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:07 +0900 Subject: [PATCH 318/626] ALSA: firewire-digi00x: refactoring to move timing of registration for isochronous channel This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. The registration of isochronous channels is done just after allocation of isochronous resources. This commit separates the registration just before starting packet streaming. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-stream.c | 41 ++++++++++++------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 4d3b4ebbdd49..455c43e81850 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -130,6 +130,12 @@ static void finish_session(struct snd_dg00x *dg00x) snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET, &data, sizeof(data), 0); + + // Unregister isochronous channels for both direction. + data = 0; + snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, + DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS, + &data, sizeof(data), 0); } static int begin_session(struct snd_dg00x *dg00x) @@ -138,6 +144,15 @@ static int begin_session(struct snd_dg00x *dg00x) u32 curr; int err; + // Register isochronous channels for both direction. + data = cpu_to_be32((dg00x->tx_resources.channel << 16) | + dg00x->rx_resources.channel); + err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, + DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS, + &data, sizeof(data), 0); + if (err < 0) + goto error; + err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST, DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_STATE, &data, sizeof(data), 0); @@ -171,13 +186,6 @@ error: static void release_resources(struct snd_dg00x *dg00x) { - __be32 data = 0; - - /* Unregister isochronous channels for both direction. */ - snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, - DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS, - &data, sizeof(data), 0); - /* Release isochronous resources. */ fw_iso_resources_free(&dg00x->tx_resources); fw_iso_resources_free(&dg00x->rx_resources); @@ -186,7 +194,6 @@ static void release_resources(struct snd_dg00x *dg00x) static int keep_resources(struct snd_dg00x *dg00x, unsigned int rate) { unsigned int i; - __be32 data; int err; /* Check sampling rate. */ @@ -216,22 +223,12 @@ static int keep_resources(struct snd_dg00x *dg00x, unsigned int rate) err = fw_iso_resources_allocate(&dg00x->tx_resources, amdtp_stream_get_max_payload(&dg00x->tx_stream), fw_parent_device(dg00x->unit)->max_speed); - if (err < 0) - goto error; - - /* Register isochronous channels for both direction. */ - data = cpu_to_be32((dg00x->tx_resources.channel << 16) | - dg00x->rx_resources.channel); - err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, - DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS, - &data, sizeof(data), 0); - if (err < 0) - goto error; + if (err < 0) { + fw_iso_resources_free(&dg00x->rx_resources); + return err; + } return 0; -error: - release_resources(dg00x); - return err; } int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x) From d18b0a6e42f7d4fca64f34ea0b76a312be632d7a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:08 +0900 Subject: [PATCH 319/626] ALSA: firewire-digi00x: code refactoring to finish streaming session This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. The operation to finish packet streaming corresponds to stopping isochronous contexts. This commit applies code refactoring to move codes to stop into a helper function to finish the session. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-stream.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 455c43e81850..90e31b63ac2f 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -125,8 +125,12 @@ int snd_dg00x_stream_get_external_rate(struct snd_dg00x *dg00x, static void finish_session(struct snd_dg00x *dg00x) { - __be32 data = cpu_to_be32(0x00000003); + __be32 data; + amdtp_stream_stop(&dg00x->tx_stream); + amdtp_stream_stop(&dg00x->rx_stream); + + data = cpu_to_be32(0x00000003); snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET, &data, sizeof(data), 0); @@ -136,6 +140,10 @@ static void finish_session(struct snd_dg00x *dg00x) snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS, &data, sizeof(data), 0); + + // Just after finishing the session, the device may lost transmitting + // functionality for a short time. + msleep(50); } static int begin_session(struct snd_dg00x *dg00x) @@ -289,8 +297,6 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate) amdtp_streaming_error(&dg00x->rx_stream)) { finish_session(dg00x); - amdtp_stream_stop(&dg00x->tx_stream); - amdtp_stream_stop(&dg00x->rx_stream); release_resources(dg00x); } @@ -346,8 +352,6 @@ end: error: finish_session(dg00x); - amdtp_stream_stop(&dg00x->tx_stream); - amdtp_stream_stop(&dg00x->rx_stream); release_resources(dg00x); return err; @@ -358,16 +362,8 @@ void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x) if (dg00x->substreams_counter > 0) return; - amdtp_stream_stop(&dg00x->tx_stream); - amdtp_stream_stop(&dg00x->rx_stream); finish_session(dg00x); release_resources(dg00x); - - /* - * Just after finishing the session, the device may lost transmitting - * functionality for a short time. - */ - msleep(50); } void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x) From 638e19fc46afceb65f6bfff65b2164fbb3324cb3 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:09 +0900 Subject: [PATCH 320/626] ALSA: firewire-digi00x: simplify error path to begin streaming session This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. The caller of begin_session() calls finish_session() in its error path, thus no need to call finish_session() in error path of begin_session(). This commit simplifies error path of begin_session(). Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-stream.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 90e31b63ac2f..8104af94aed5 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -159,13 +159,13 @@ static int begin_session(struct snd_dg00x *dg00x) DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS, &data, sizeof(data), 0); if (err < 0) - goto error; + return err; err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST, DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_STATE, &data, sizeof(data), 0); if (err < 0) - goto error; + return err; curr = be32_to_cpu(data); if (curr == 0) @@ -180,15 +180,12 @@ static int begin_session(struct snd_dg00x *dg00x) DG00X_OFFSET_STREAMING_SET, &data, sizeof(data), 0); if (err < 0) - goto error; + break; msleep(20); curr--; } - return 0; -error: - finish_session(dg00x); return err; } From ad3065054761c86d3284315b67512a70f5ae0c04 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:10 +0900 Subject: [PATCH 321/626] ALSA: firewire-digi00x: code refactoring to keep isochronous resources This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. All of models in Digidesign Digi00x family have the same formation of data channels in isochronous packet for both directions. This commit simplifies allocation of isochronous resources in this point. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-stream.c | 42 +++++++++++-------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 8104af94aed5..2bddeb3e4bf5 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -196,12 +196,14 @@ static void release_resources(struct snd_dg00x *dg00x) fw_iso_resources_free(&dg00x->rx_resources); } -static int keep_resources(struct snd_dg00x *dg00x, unsigned int rate) +static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream, + unsigned int rate) { - unsigned int i; + struct fw_iso_resources *resources; + int i; int err; - /* Check sampling rate. */ + // Check sampling rate. for (i = 0; i < SND_DG00X_RATE_COUNT; i++) { if (snd_dg00x_stream_rates[i] == rate) break; @@ -209,31 +211,19 @@ static int keep_resources(struct snd_dg00x *dg00x, unsigned int rate) if (i == SND_DG00X_RATE_COUNT) return -EINVAL; - /* Keep resources for out-stream. */ - err = amdtp_dot_set_parameters(&dg00x->rx_stream, rate, + if (stream == &dg00x->tx_stream) + resources = &dg00x->tx_resources; + else + resources = &dg00x->rx_resources; + + err = amdtp_dot_set_parameters(stream, rate, snd_dg00x_stream_pcm_channels[i]); if (err < 0) return err; - err = fw_iso_resources_allocate(&dg00x->rx_resources, - amdtp_stream_get_max_payload(&dg00x->rx_stream), - fw_parent_device(dg00x->unit)->max_speed); - if (err < 0) - return err; - /* Keep resources for in-stream. */ - err = amdtp_dot_set_parameters(&dg00x->tx_stream, rate, - snd_dg00x_stream_pcm_channels[i]); - if (err < 0) - return err; - err = fw_iso_resources_allocate(&dg00x->tx_resources, - amdtp_stream_get_max_payload(&dg00x->tx_stream), + return fw_iso_resources_allocate(resources, + amdtp_stream_get_max_payload(stream), fw_parent_device(dg00x->unit)->max_speed); - if (err < 0) { - fw_iso_resources_free(&dg00x->rx_resources); - return err; - } - - return 0; } int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x) @@ -306,7 +296,11 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate) if (err < 0) goto error; - err = keep_resources(dg00x, rate); + err = keep_resources(dg00x, &dg00x->rx_stream, rate); + if (err < 0) + goto error; + + err = keep_resources(dg00x, &dg00x->tx_stream, rate); if (err < 0) goto error; From ae8ffbb26512bbfd3f929e34c85880f620ecb6eb Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:11 +0900 Subject: [PATCH 322/626] ALSA: firewire-digi00x: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Once allocated, isochronous resources are available for packet streaming, even if the streaming is cancelled. For this reason, current implementation handles allocation of the resources and starting packet streaming at the same time. However, this brings complicated procedure to start packet streaming. This commit separates the allocation and starting. The allocation is done in pcm.hw_params callback and available till pcm.hw_free callback. Even if any XRUN occurs, pcm.prepare callback is done to restart packet streaming without releasing/allocating the resources. There are two points to stop packet streaming; in pcm.hw_params and pcm.prepare callbacks. The former point is a case that packet streaming is already started for any MIDI substream then packet streaming is requested with different sampling transfer frequency for any PCM substream. The latter point is cases of any XRUN or packet queueing error. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-midi.c | 10 ++- sound/firewire/digi00x/digi00x-pcm.c | 28 +++++--- sound/firewire/digi00x/digi00x-stream.c | 92 ++++++++++++++----------- sound/firewire/digi00x/digi00x.h | 4 +- 4 files changed, 78 insertions(+), 56 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-midi.c b/sound/firewire/digi00x/digi00x-midi.c index 7ab3d0810f6b..cca888cce0d3 100644 --- a/sound/firewire/digi00x/digi00x-midi.c +++ b/sound/firewire/digi00x/digi00x-midi.c @@ -18,8 +18,11 @@ static int midi_open(struct snd_rawmidi_substream *substream) return err; mutex_lock(&dg00x->mutex); - dg00x->substreams_counter++; - err = snd_dg00x_stream_start_duplex(dg00x, 0); + err = snd_dg00x_stream_reserve_duplex(dg00x, 0); + if (err >= 0) { + ++dg00x->substreams_counter; + err = snd_dg00x_stream_start_duplex(dg00x); + } mutex_unlock(&dg00x->mutex); if (err < 0) snd_dg00x_stream_lock_release(dg00x); @@ -32,8 +35,9 @@ static int midi_close(struct snd_rawmidi_substream *substream) struct snd_dg00x *dg00x = substream->rmidi->private_data; mutex_lock(&dg00x->mutex); - dg00x->substreams_counter--; + --dg00x->substreams_counter; snd_dg00x_stream_stop_duplex(dg00x); + snd_dg00x_stream_release_duplex(dg00x); mutex_unlock(&dg00x->mutex); snd_dg00x_stream_lock_release(dg00x); diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index fdcff0460c53..1c04747f4fcc 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -167,12 +167,16 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&dg00x->mutex); - dg00x->substreams_counter++; + err = snd_dg00x_stream_reserve_duplex(dg00x, rate); + if (err >= 0) + ++dg00x->substreams_counter; mutex_unlock(&dg00x->mutex); } - return 0; + return err; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, @@ -187,12 +191,16 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&dg00x->mutex); - dg00x->substreams_counter++; + err = snd_dg00x_stream_reserve_duplex(dg00x, rate); + if (err >= 0) + ++dg00x->substreams_counter; mutex_unlock(&dg00x->mutex); } - return 0; + return err; } static int pcm_capture_hw_free(struct snd_pcm_substream *substream) @@ -202,9 +210,10 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dg00x->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - dg00x->substreams_counter--; + --dg00x->substreams_counter; snd_dg00x_stream_stop_duplex(dg00x); + snd_dg00x_stream_release_duplex(dg00x); mutex_unlock(&dg00x->mutex); @@ -218,9 +227,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dg00x->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - dg00x->substreams_counter--; + --dg00x->substreams_counter; snd_dg00x_stream_stop_duplex(dg00x); + snd_dg00x_stream_release_duplex(dg00x); mutex_unlock(&dg00x->mutex); @@ -230,12 +240,11 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) static int pcm_capture_prepare(struct snd_pcm_substream *substream) { struct snd_dg00x *dg00x = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; mutex_lock(&dg00x->mutex); - err = snd_dg00x_stream_start_duplex(dg00x, runtime->rate); + err = snd_dg00x_stream_start_duplex(dg00x); if (err >= 0) amdtp_stream_pcm_prepare(&dg00x->tx_stream); @@ -247,12 +256,11 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) static int pcm_playback_prepare(struct snd_pcm_substream *substream) { struct snd_dg00x *dg00x = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; mutex_lock(&dg00x->mutex); - err = snd_dg00x_stream_start_duplex(dg00x, runtime->rate); + err = snd_dg00x_stream_start_duplex(dg00x); if (err >= 0) { amdtp_stream_pcm_prepare(&dg00x->rx_stream); amdtp_dot_reset(&dg00x->rx_stream); diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 2bddeb3e4bf5..3b903e42d29a 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -189,13 +189,6 @@ static int begin_session(struct snd_dg00x *dg00x) return err; } -static void release_resources(struct snd_dg00x *dg00x) -{ - /* Release isochronous resources. */ - fw_iso_resources_free(&dg00x->tx_resources); - fw_iso_resources_free(&dg00x->rx_resources); -} - static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream, unsigned int rate) { @@ -265,45 +258,65 @@ void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x) fw_iso_resources_destroy(&dg00x->tx_resources); } -int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate) +int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate) { unsigned int curr_rate; + int err; + + err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate); + if (err < 0) + return err; + if (rate == 0) + rate = curr_rate; + + if (dg00x->substreams_counter == 0 || curr_rate != rate) { + finish_session(dg00x); + + fw_iso_resources_free(&dg00x->tx_resources); + fw_iso_resources_free(&dg00x->rx_resources); + + err = snd_dg00x_stream_set_local_rate(dg00x, rate); + if (err < 0) + return err; + + err = keep_resources(dg00x, &dg00x->rx_stream, rate); + if (err < 0) + return err; + + err = keep_resources(dg00x, &dg00x->tx_stream, rate); + if (err < 0) { + fw_iso_resources_free(&dg00x->rx_resources); + return err; + } + } + + return 0; +} + +void snd_dg00x_stream_release_duplex(struct snd_dg00x *dg00x) +{ + if (dg00x->substreams_counter == 0) { + fw_iso_resources_free(&dg00x->tx_resources); + fw_iso_resources_free(&dg00x->rx_resources); + } +} + +int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) +{ int err = 0; if (dg00x->substreams_counter == 0) - goto end; + return 0; - /* Check current sampling rate. */ - err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate); - if (err < 0) - goto error; - if (rate == 0) - rate = curr_rate; - if (curr_rate != rate || - amdtp_streaming_error(&dg00x->tx_stream) || - amdtp_streaming_error(&dg00x->rx_stream)) { + if (amdtp_streaming_error(&dg00x->tx_stream) || + amdtp_streaming_error(&dg00x->rx_stream)) finish_session(dg00x); - release_resources(dg00x); - } - /* * No packets are transmitted without receiving packets, reagardless of * which source of clock is used. */ if (!amdtp_stream_running(&dg00x->rx_stream)) { - err = snd_dg00x_stream_set_local_rate(dg00x, rate); - if (err < 0) - goto error; - - err = keep_resources(dg00x, &dg00x->rx_stream, rate); - if (err < 0) - goto error; - - err = keep_resources(dg00x, &dg00x->tx_stream, rate); - if (err < 0) - goto error; - err = begin_session(dg00x); if (err < 0) goto error; @@ -338,23 +351,18 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate) goto error; } } -end: - return err; + + return 0; error: finish_session(dg00x); - release_resources(dg00x); - return err; } void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x) { - if (dg00x->substreams_counter > 0) - return; - - finish_session(dg00x); - release_resources(dg00x); + if (dg00x->substreams_counter == 0) + finish_session(dg00x); } void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x) diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 4dd1bbf2ed3c..3fb1c49f6f9e 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h @@ -140,8 +140,10 @@ int snd_dg00x_stream_get_clock(struct snd_dg00x *dg00x, int snd_dg00x_stream_check_external_clock(struct snd_dg00x *dg00x, bool *detect); int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x); -int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate); +int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate); +int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x); void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x); +void snd_dg00x_stream_release_duplex(struct snd_dg00x *dg00x); void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x); void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x); From 24bb77b3fff442cab2a6f4227ffcf40fd713816f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:12 +0900 Subject: [PATCH 323/626] ALSA: firewire-digi00x: update isochronous resources when starting packet streaming after bus-reset After bus reset, isochronous resource manager releases all of allocated isochronous resources. The nodes to transfer isochronous packet should request reallocation of the resources. However, between the bus-reset and invocation of 'struct fw_driver.update' handler, ALSA PCM application can detect this situation by XRUN because the target device cancelled to transmit packets once bus-reset occurs. Due to the above mechanism, ALSA fireface driver just stops packet streaming in the update handler, thus pcm.prepare handler should request the reallocation. This commit requests the reallocation in pcm.prepare callback when bus generation is changed. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-stream.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 3b903e42d29a..3c5e1c5a2e11 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -303,6 +303,7 @@ void snd_dg00x_stream_release_duplex(struct snd_dg00x *dg00x) int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) { + unsigned int generation = dg00x->rx_resources.generation; int err = 0; if (dg00x->substreams_counter == 0) @@ -312,6 +313,16 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) amdtp_streaming_error(&dg00x->rx_stream)) finish_session(dg00x); + if (generation != fw_parent_device(dg00x->unit)->card->generation) { + err = fw_iso_resources_update(&dg00x->tx_resources); + if (err < 0) + goto error; + + err = fw_iso_resources_update(&dg00x->rx_resources); + if (err < 0) + goto error; + } + /* * No packets are transmitted without receiving packets, reagardless of * which source of clock is used. From 478f3a56dcbc991b5d1d0e72666b0b32bae5e0a8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:13 +0900 Subject: [PATCH 324/626] ALSA: firewire-digi00x: code refactoring for pcm.hw_params/hw_free callbacks The pairs of pcm.hw_params callbacks and .hw_free callbacks for both direction have no differences. This commit unifies the pairs. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-pcm.c | 55 ++++------------------------ 1 file changed, 7 insertions(+), 48 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index 1c04747f4fcc..9ed2ebdcf23a 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -155,8 +155,8 @@ static int pcm_close(struct snd_pcm_substream *substream) return 0; } -static int pcm_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_dg00x *dg00x = substream->private_data; int err; @@ -179,48 +179,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, return err; } -static int pcm_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_dg00x *dg00x = substream->private_data; - int err; - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { - unsigned int rate = params_rate(hw_params); - - mutex_lock(&dg00x->mutex); - err = snd_dg00x_stream_reserve_duplex(dg00x, rate); - if (err >= 0) - ++dg00x->substreams_counter; - mutex_unlock(&dg00x->mutex); - } - - return err; -} - -static int pcm_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_dg00x *dg00x = substream->private_data; - - mutex_lock(&dg00x->mutex); - - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - --dg00x->substreams_counter; - - snd_dg00x_stream_stop_duplex(dg00x); - snd_dg00x_stream_release_duplex(dg00x); - - mutex_unlock(&dg00x->mutex); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static int pcm_playback_hw_free(struct snd_pcm_substream *substream) +static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_dg00x *dg00x = substream->private_data; @@ -341,8 +300,8 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_capture_hw_params, - .hw_free = pcm_capture_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, @@ -353,8 +312,8 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_playback_hw_params, - .hw_free = pcm_playback_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, From b3480638a52adeeb133759fca0a0f89ce403e8ba Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:14 +0900 Subject: [PATCH 325/626] ALSA: dice: code refactoring to stop packet streaming This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. There're three points to finish packet streaming but no helper functions for common operations for it. This commit adds a helper function for operations to finish packet streaming. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-stream.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index c3c892c5c7ff..8bce923dc4bd 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -230,6 +230,15 @@ static int keep_resources(struct snd_dice *dice, fw_parent_device(dice->unit)->max_speed); } +static void finish_session(struct snd_dice *dice, struct reg_params *tx_params, + struct reg_params *rx_params) +{ + stop_streams(dice, AMDTP_IN_STREAM, tx_params); + stop_streams(dice, AMDTP_OUT_STREAM, rx_params); + + snd_dice_transaction_clear_enable(dice); +} + static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, unsigned int rate, struct reg_params *params) { @@ -328,10 +337,8 @@ static int start_duplex_streams(struct snd_dice *dice, unsigned int rate) if (err < 0) return err; - /* Stop transmission. */ - stop_streams(dice, AMDTP_IN_STREAM, &tx_params); - stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); - snd_dice_transaction_clear_enable(dice); + // Stop transmission. + finish_session(dice, &tx_params, &rx_params); release_resources(dice); err = ensure_phase_lock(dice, rate); @@ -373,9 +380,7 @@ static int start_duplex_streams(struct snd_dice *dice, unsigned int rate) return 0; error: - stop_streams(dice, AMDTP_IN_STREAM, &tx_params); - stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); - snd_dice_transaction_clear_enable(dice); + finish_session(dice, &tx_params, &rx_params); release_resources(dice); return err; } @@ -449,12 +454,8 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice) if (dice->substreams_counter > 0) return; - snd_dice_transaction_clear_enable(dice); - - if (get_register_params(dice, &tx_params, &rx_params) == 0) { - stop_streams(dice, AMDTP_IN_STREAM, &tx_params); - stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); - } + if (get_register_params(dice, &tx_params, &rx_params) >= 0) + finish_session(dice, &tx_params, &rx_params); release_resources(dice); } From c738aed136a74e9fafd90e5c8a0b13bf068a39f7 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:15 +0900 Subject: [PATCH 326/626] ALSA: dice: code refactoring to keep isochronous resources This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. This commit adds a helper function to allocate isochronous resources, separated from operations to start packet streaming, I note that some dice-based devices have two pair of endpoints for isochronous packet straeming. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-stream.c | 165 ++++++++++++++++-------------- 1 file changed, 90 insertions(+), 75 deletions(-) diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index 8bce923dc4bd..010cbf02de4f 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -175,35 +175,22 @@ static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, } } -static int keep_resources(struct snd_dice *dice, - enum amdtp_stream_direction dir, unsigned int index, - unsigned int rate, unsigned int pcm_chs, - unsigned int midi_ports) +static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream, + struct fw_iso_resources *resources, unsigned int rate, + unsigned int pcm_chs, unsigned int midi_ports) { - struct amdtp_stream *stream; - struct fw_iso_resources *resources; bool double_pcm_frames; unsigned int i; int err; - if (dir == AMDTP_IN_STREAM) { - stream = &dice->tx_stream[index]; - resources = &dice->tx_resources[index]; - } else { - stream = &dice->rx_stream[index]; - resources = &dice->rx_resources[index]; - } - - /* - * At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in - * one data block of AMDTP packet. Thus sampling transfer frequency is - * a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are - * transferred on AMDTP packets at 96 kHz. Two successive samples of a - * channel are stored consecutively in the packet. This quirk is called - * as 'Dual Wire'. - * For this quirk, blocking mode is required and PCM buffer size should - * be aligned to SYT_INTERVAL. - */ + // At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in + // one data block of AMDTP packet. Thus sampling transfer frequency is + // a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are + // transferred on AMDTP packets at 96 kHz. Two successive samples of a + // channel are stored consecutively in the packet. This quirk is called + // as 'Dual Wire'. + // For this quirk, blocking mode is required and PCM buffer size should + // be aligned to SYT_INTERVAL. double_pcm_frames = rate > 96000; if (double_pcm_frames) { rate /= 2; @@ -230,6 +217,68 @@ static int keep_resources(struct snd_dice *dice, fw_parent_device(dice->unit)->max_speed); } +static int keep_dual_resources(struct snd_dice *dice, unsigned int rate, + enum amdtp_stream_direction dir, + struct reg_params *params) +{ + enum snd_dice_rate_mode mode; + int i; + int err; + + err = snd_dice_stream_get_rate_mode(dice, rate, &mode); + if (err < 0) + return err; + + for (i = 0; i < params->count; ++i) { + __be32 reg[2]; + struct amdtp_stream *stream; + struct fw_iso_resources *resources; + unsigned int pcm_cache; + unsigned int midi_cache; + unsigned int pcm_chs; + unsigned int midi_ports; + + if (dir == AMDTP_IN_STREAM) { + stream = &dice->tx_stream[i]; + resources = &dice->tx_resources[i]; + + pcm_cache = dice->tx_pcm_chs[i][mode]; + midi_cache = dice->tx_midi_ports[i]; + err = snd_dice_transaction_read_tx(dice, + params->size * i + TX_NUMBER_AUDIO, + reg, sizeof(reg)); + } else { + stream = &dice->rx_stream[i]; + resources = &dice->rx_resources[i]; + + pcm_cache = dice->rx_pcm_chs[i][mode]; + midi_cache = dice->rx_midi_ports[i]; + err = snd_dice_transaction_read_rx(dice, + params->size * i + RX_NUMBER_AUDIO, + reg, sizeof(reg)); + } + if (err < 0) + return err; + pcm_chs = be32_to_cpu(reg[0]); + midi_ports = be32_to_cpu(reg[1]); + + // These are important for developer of this driver. + if (pcm_chs != pcm_cache || midi_ports != midi_cache) { + dev_info(&dice->unit->device, + "cache mismatch: pcm: %u:%u, midi: %u:%u\n", + pcm_chs, pcm_cache, midi_ports, midi_cache); + return -EPROTO; + } + + err = keep_resources(dice, stream, resources, rate, pcm_chs, + midi_ports); + if (err < 0) + return err; + } + + return 0; +} + static void finish_session(struct snd_dice *dice, struct reg_params *tx_params, struct reg_params *rx_params) { @@ -242,84 +291,50 @@ static void finish_session(struct snd_dice *dice, struct reg_params *tx_params, static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, unsigned int rate, struct reg_params *params) { - __be32 reg[2]; - enum snd_dice_rate_mode mode; - unsigned int i, pcm_chs, midi_ports; - struct amdtp_stream *streams; - struct fw_iso_resources *resources; - struct fw_device *fw_dev = fw_parent_device(dice->unit); - int err = 0; + unsigned int max_speed = fw_parent_device(dice->unit)->max_speed; + int i; + int err; - if (dir == AMDTP_IN_STREAM) { - streams = dice->tx_stream; - resources = dice->tx_resources; - } else { - streams = dice->rx_stream; - resources = dice->rx_resources; - } - - err = snd_dice_stream_get_rate_mode(dice, rate, &mode); + err = keep_dual_resources(dice, rate, dir, params); if (err < 0) return err; for (i = 0; i < params->count; i++) { - unsigned int pcm_cache; - unsigned int midi_cache; + struct amdtp_stream *stream; + struct fw_iso_resources *resources; + __be32 reg; if (dir == AMDTP_IN_STREAM) { - pcm_cache = dice->tx_pcm_chs[i][mode]; - midi_cache = dice->tx_midi_ports[i]; - err = snd_dice_transaction_read_tx(dice, - params->size * i + TX_NUMBER_AUDIO, - reg, sizeof(reg)); + stream = dice->tx_stream + i; + resources = dice->tx_resources + i; } else { - pcm_cache = dice->rx_pcm_chs[i][mode]; - midi_cache = dice->rx_midi_ports[i]; - err = snd_dice_transaction_read_rx(dice, - params->size * i + RX_NUMBER_AUDIO, - reg, sizeof(reg)); - } - if (err < 0) - return err; - pcm_chs = be32_to_cpu(reg[0]); - midi_ports = be32_to_cpu(reg[1]); - - /* These are important for developer of this driver. */ - if (pcm_chs != pcm_cache || midi_ports != midi_cache) { - dev_info(&dice->unit->device, - "cache mismatch: pcm: %u:%u, midi: %u:%u\n", - pcm_chs, pcm_cache, midi_ports, midi_cache); - return -EPROTO; + stream = dice->rx_stream + i; + resources = dice->rx_resources + i; } - err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports); - if (err < 0) - return err; - - reg[0] = cpu_to_be32(resources[i].channel); + reg = cpu_to_be32(resources->channel); if (dir == AMDTP_IN_STREAM) { err = snd_dice_transaction_write_tx(dice, params->size * i + TX_ISOCHRONOUS, - reg, sizeof(reg[0])); + ®, sizeof(reg)); } else { err = snd_dice_transaction_write_rx(dice, params->size * i + RX_ISOCHRONOUS, - reg, sizeof(reg[0])); + ®, sizeof(reg)); } if (err < 0) return err; if (dir == AMDTP_IN_STREAM) { - reg[0] = cpu_to_be32(fw_dev->max_speed); + reg = cpu_to_be32(max_speed); err = snd_dice_transaction_write_tx(dice, params->size * i + TX_SPEED, - reg, sizeof(reg[0])); + ®, sizeof(reg)); if (err < 0) return err; } - err = amdtp_stream_start(&streams[i], resources[i].channel, - fw_dev->max_speed); + err = amdtp_stream_start(stream, resources->channel, max_speed); if (err < 0) return err; } From 3cd2c2d780a23e8b847c9ec22e8bc9dd6e685cbe Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:16 +0900 Subject: [PATCH 327/626] ALSA: dice: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Once allocated, isochronous resources are available for packet streaming, even if the streaming is cancelled. For this reason, current implementation handles allocation of the resources and starting packet streaming at the same time. However, this brings complicated procedure to start packet streaming. This commit separates the allocation and starting. The allocation is done in pcm.hw_params callback and available till pcm.hw_free callback. Even if any XRUN occurs, pcm.prepare callback is done to restart packet streaming without releasing/allocating the resources. There are two points to stop packet streaming; in pcm.hw_params and pcm.prepare callbacks. The former point is a case that packet streaming is already started for any MIDI substream then packet streaming is requested with different sampling transfer frequency for any PCM substream. The latter point is cases of any XRUN or packet queueing error. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-midi.c | 10 +- sound/firewire/dice/dice-pcm.c | 26 ++-- sound/firewire/dice/dice-stream.c | 218 ++++++++++++++++-------------- sound/firewire/dice/dice.h | 4 +- 4 files changed, 143 insertions(+), 115 deletions(-) diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c index 84eca8a51a02..6172dad87c4e 100644 --- a/sound/firewire/dice/dice-midi.c +++ b/sound/firewire/dice/dice-midi.c @@ -18,8 +18,11 @@ static int midi_open(struct snd_rawmidi_substream *substream) mutex_lock(&dice->mutex); - dice->substreams_counter++; - err = snd_dice_stream_start_duplex(dice, 0); + err = snd_dice_stream_reserve_duplex(dice, 0); + if (err >= 0) { + ++dice->substreams_counter; + err = snd_dice_stream_start_duplex(dice); + } mutex_unlock(&dice->mutex); @@ -35,8 +38,9 @@ static int midi_close(struct snd_rawmidi_substream *substream) mutex_lock(&dice->mutex); - dice->substreams_counter--; + --dice->substreams_counter; snd_dice_stream_stop_duplex(dice); + snd_dice_stream_release_duplex(dice); mutex_unlock(&dice->mutex); diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index bb3ef5ff3488..6c7a6b7ed743 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -243,12 +243,16 @@ static int capture_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&dice->mutex); - dice->substreams_counter++; + err = snd_dice_stream_reserve_duplex(dice, rate); + if (err >= 0) + ++dice->substreams_counter; mutex_unlock(&dice->mutex); } - return 0; + return err; } static int playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) @@ -262,12 +266,16 @@ static int playback_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&dice->mutex); - dice->substreams_counter++; + err = snd_dice_stream_reserve_duplex(dice, rate); + if (err >= 0) + ++dice->substreams_counter; mutex_unlock(&dice->mutex); } - return 0; + return err; } static int capture_hw_free(struct snd_pcm_substream *substream) @@ -277,9 +285,10 @@ static int capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dice->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - dice->substreams_counter--; + --dice->substreams_counter; snd_dice_stream_stop_duplex(dice); + snd_dice_stream_release_duplex(dice); mutex_unlock(&dice->mutex); @@ -293,9 +302,10 @@ static int playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dice->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - dice->substreams_counter--; + --dice->substreams_counter; snd_dice_stream_stop_duplex(dice); + snd_dice_stream_release_duplex(dice); mutex_unlock(&dice->mutex); @@ -309,7 +319,7 @@ static int capture_prepare(struct snd_pcm_substream *substream) int err; mutex_lock(&dice->mutex); - err = snd_dice_stream_start_duplex(dice, substream->runtime->rate); + err = snd_dice_stream_start_duplex(dice); mutex_unlock(&dice->mutex); if (err >= 0) amdtp_stream_pcm_prepare(stream); @@ -323,7 +333,7 @@ static int playback_prepare(struct snd_pcm_substream *substream) int err; mutex_lock(&dice->mutex); - err = snd_dice_stream_start_duplex(dice, substream->runtime->rate); + err = snd_dice_stream_start_duplex(dice); mutex_unlock(&dice->mutex); if (err >= 0) amdtp_stream_pcm_prepare(stream); diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index 010cbf02de4f..6bbf7421a53c 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -138,18 +138,9 @@ static int get_register_params(struct snd_dice *dice, static void release_resources(struct snd_dice *dice) { - unsigned int i; - - for (i = 0; i < MAX_STREAMS; i++) { - if (amdtp_stream_running(&dice->tx_stream[i])) { - amdtp_stream_pcm_abort(&dice->tx_stream[i]); - amdtp_stream_stop(&dice->tx_stream[i]); - } - if (amdtp_stream_running(&dice->rx_stream[i])) { - amdtp_stream_pcm_abort(&dice->rx_stream[i]); - amdtp_stream_stop(&dice->rx_stream[i]); - } + int i; + for (i = 0; i < MAX_STREAMS; ++i) { fw_iso_resources_free(&dice->tx_resources[i]); fw_iso_resources_free(&dice->rx_resources[i]); } @@ -164,10 +155,14 @@ static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, for (i = 0; i < params->count; i++) { reg = cpu_to_be32((u32)-1); if (dir == AMDTP_IN_STREAM) { + amdtp_stream_stop(&dice->tx_stream[i]); + snd_dice_transaction_write_tx(dice, params->size * i + TX_ISOCHRONOUS, ®, sizeof(reg)); } else { + amdtp_stream_stop(&dice->rx_stream[i]); + snd_dice_transaction_write_rx(dice, params->size * i + RX_ISOCHRONOUS, ®, sizeof(reg)); @@ -288,6 +283,65 @@ static void finish_session(struct snd_dice *dice, struct reg_params *tx_params, snd_dice_transaction_clear_enable(dice); } +int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate) +{ + unsigned int curr_rate; + int err; + + // Check sampling transmission frequency. + err = snd_dice_transaction_get_rate(dice, &curr_rate); + if (err < 0) + return err; + if (rate == 0) + rate = curr_rate; + + if (dice->substreams_counter == 0 || curr_rate != rate) { + struct reg_params tx_params, rx_params; + + err = get_register_params(dice, &tx_params, &rx_params); + if (err < 0) + return err; + + finish_session(dice, &tx_params, &rx_params); + + release_resources(dice); + + // Just after owning the unit (GLOBAL_OWNER), the unit can + // return invalid stream formats. Selecting clock parameters + // have an effect for the unit to refine it. + err = ensure_phase_lock(dice, rate); + if (err < 0) + return err; + + // After changing sampling transfer frequency, the value of + // register can be changed. + err = get_register_params(dice, &tx_params, &rx_params); + if (err < 0) + return err; + + err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM, + &tx_params); + if (err < 0) + goto error; + + err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM, + &rx_params); + if (err < 0) + goto error; + } + + return 0; +error: + release_resources(dice); + return err; +} + +void snd_dice_stream_release_duplex(struct snd_dice *dice) +{ + if (dice->substreams_counter == 0) + release_resources(dice); +} + static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, unsigned int rate, struct reg_params *params) { @@ -295,10 +349,6 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, int i; int err; - err = keep_dual_resources(dice, rate, dir, params); - if (err < 0) - return err; - for (i = 0; i < params->count; i++) { struct amdtp_stream *stream; struct fw_iso_resources *resources; @@ -342,102 +392,39 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, return err; } -static int start_duplex_streams(struct snd_dice *dice, unsigned int rate) -{ - struct reg_params tx_params, rx_params; - int i; - int err; - - err = get_register_params(dice, &tx_params, &rx_params); - if (err < 0) - return err; - - // Stop transmission. - finish_session(dice, &tx_params, &rx_params); - release_resources(dice); - - err = ensure_phase_lock(dice, rate); - if (err < 0) { - dev_err(&dice->unit->device, "fail to ensure phase lock\n"); - return err; - } - - /* Likely to have changed stream formats. */ - err = get_register_params(dice, &tx_params, &rx_params); - if (err < 0) - return err; - - /* Start both streams. */ - err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params); - if (err < 0) - goto error; - err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params); - if (err < 0) - goto error; - - err = snd_dice_transaction_set_enable(dice); - if (err < 0) { - dev_err(&dice->unit->device, "fail to enable interface\n"); - goto error; - } - - for (i = 0; i < MAX_STREAMS; i++) { - if ((i < tx_params.count && - !amdtp_stream_wait_callback(&dice->tx_stream[i], - CALLBACK_TIMEOUT)) || - (i < rx_params.count && - !amdtp_stream_wait_callback(&dice->rx_stream[i], - CALLBACK_TIMEOUT))) { - err = -ETIMEDOUT; - goto error; - } - } - - return 0; -error: - finish_session(dice, &tx_params, &rx_params); - release_resources(dice); - return err; -} - /* * MEMO: After this function, there're two states of streams: * - None streams are running. * - All streams are running. */ -int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate) +int snd_dice_stream_start_duplex(struct snd_dice *dice) { - unsigned int curr_rate; + struct reg_params tx_params, rx_params; unsigned int i; + unsigned int rate; enum snd_dice_rate_mode mode; int err; if (dice->substreams_counter == 0) return -EIO; - /* Check sampling transmission frequency. */ - err = snd_dice_transaction_get_rate(dice, &curr_rate); - if (err < 0) { - dev_err(&dice->unit->device, - "fail to get sampling rate\n"); + err = get_register_params(dice, &tx_params, &rx_params); + if (err < 0) return err; - } - if (rate == 0) - rate = curr_rate; - if (rate != curr_rate) - goto restart; - /* Check error of packet streaming. */ + // Check error of packet streaming. for (i = 0; i < MAX_STREAMS; ++i) { - if (amdtp_streaming_error(&dice->tx_stream[i])) - break; - if (amdtp_streaming_error(&dice->rx_stream[i])) + if (amdtp_streaming_error(&dice->tx_stream[i]) || + amdtp_streaming_error(&dice->rx_stream[i])) { + finish_session(dice, &tx_params, &rx_params); break; + } } - if (i < MAX_STREAMS) - goto restart; - /* Check required streams are running or not. */ + // Check required streams are running or not. + err = snd_dice_transaction_get_rate(dice, &rate); + if (err < 0) + return err; err = snd_dice_stream_get_rate_mode(dice, rate, &mode); if (err < 0) return err; @@ -449,12 +436,40 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate) !amdtp_stream_running(&dice->rx_stream[i])) break; } - if (i < MAX_STREAMS) - goto restart; + if (i < MAX_STREAMS) { + // Start both streams. + err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params); + if (err < 0) + goto error; + + err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params); + if (err < 0) + goto error; + + err = snd_dice_transaction_set_enable(dice); + if (err < 0) { + dev_err(&dice->unit->device, + "fail to enable interface\n"); + goto error; + } + + for (i = 0; i < MAX_STREAMS; i++) { + if ((i < tx_params.count && + !amdtp_stream_wait_callback(&dice->tx_stream[i], + CALLBACK_TIMEOUT)) || + (i < rx_params.count && + !amdtp_stream_wait_callback(&dice->rx_stream[i], + CALLBACK_TIMEOUT))) { + err = -ETIMEDOUT; + goto error; + } + } + } return 0; -restart: - return start_duplex_streams(dice, rate); +error: + finish_session(dice, &tx_params, &rx_params); + return err; } /* @@ -466,13 +481,10 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice) { struct reg_params tx_params, rx_params; - if (dice->substreams_counter > 0) - return; - - if (get_register_params(dice, &tx_params, &rx_params) >= 0) - finish_session(dice, &tx_params, &rx_params); - - release_resources(dice); + if (dice->substreams_counter == 0) { + if (get_register_params(dice, &tx_params, &rx_params) >= 0) + finish_session(dice, &tx_params, &rx_params); + } } static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir, diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 9699adc2a96d..f95073b85010 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -205,10 +205,12 @@ extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT]; int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate, enum snd_dice_rate_mode *mode); -int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate); +int snd_dice_stream_start_duplex(struct snd_dice *dice); void snd_dice_stream_stop_duplex(struct snd_dice *dice); int snd_dice_stream_init_duplex(struct snd_dice *dice); void snd_dice_stream_destroy_duplex(struct snd_dice *dice); +int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate); +void snd_dice_stream_release_duplex(struct snd_dice *dice); void snd_dice_stream_update_duplex(struct snd_dice *dice); int snd_dice_stream_detect_current_formats(struct snd_dice *dice); From d5553026b53a246861d00221a6beb3674a30df03 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:17 +0900 Subject: [PATCH 328/626] ALSA: dice: update isochronous resources when starting packet streaming after bus-reset After bus reset, isochronous resource manager releases all of allocated isochronous resources. The nodes to transfer isochronous packet should request reallocation of the resources. However, between the bus-reset and invocation of 'struct fw_driver.update' handler, ALSA PCM application can detect this situation by XRUN because the target device cancelled to transmit packets once bus-reset occurs. Due to the above mechanism, ALSA fireface driver just stops packet streaming in the update handler, thus pcm.prepare handler should request the reallocation. This commit requests the reallocation in pcm.prepare callback when bus generation is changed. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-stream.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index 6bbf7421a53c..f61b99a72655 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -399,6 +399,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, */ int snd_dice_stream_start_duplex(struct snd_dice *dice) { + unsigned int generation = dice->rx_resources[0].generation; struct reg_params tx_params, rx_params; unsigned int i; unsigned int rate; @@ -421,6 +422,15 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice) } } + if (generation != fw_parent_device(dice->unit)->card->generation) { + for (i = 0; i < MAX_STREAMS; ++i) { + if (i < tx_params.count) + fw_iso_resources_update(dice->tx_resources + i); + if (i < rx_params.count) + fw_iso_resources_update(dice->rx_resources + i); + } + } + // Check required streams are running or not. err = snd_dice_transaction_get_rate(dice, &rate); if (err < 0) From 4dbf4f44cf8363603cb7e205620aec7255d3508c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 11 Jun 2019 22:21:18 +0900 Subject: [PATCH 329/626] ALSA: dice: code refactoring for pcm.hw_params/hw_free callbacks The pairs of pcm.hw_params callbacks and .hw_free callbacks for both direction have no differences. This commit unifies the pairs. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-pcm.c | 54 +++++----------------------------- 1 file changed, 7 insertions(+), 47 deletions(-) diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 6c7a6b7ed743..00b55dfc3b2c 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -231,31 +231,8 @@ static int pcm_close(struct snd_pcm_substream *substream) return 0; } -static int capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_dice *dice = substream->private_data; - int err; - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { - unsigned int rate = params_rate(hw_params); - - mutex_lock(&dice->mutex); - err = snd_dice_stream_reserve_duplex(dice, rate); - if (err >= 0) - ++dice->substreams_counter; - mutex_unlock(&dice->mutex); - } - - return err; -} -static int playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_dice *dice = substream->private_data; int err; @@ -278,24 +255,7 @@ static int playback_hw_params(struct snd_pcm_substream *substream, return err; } -static int capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_dice *dice = substream->private_data; - - mutex_lock(&dice->mutex); - - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - --dice->substreams_counter; - - snd_dice_stream_stop_duplex(dice); - snd_dice_stream_release_duplex(dice); - - mutex_unlock(&dice->mutex); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static int playback_hw_free(struct snd_pcm_substream *substream) +static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_dice *dice = substream->private_data; @@ -415,8 +375,8 @@ int snd_dice_create_pcm(struct snd_dice *dice) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = capture_hw_params, - .hw_free = capture_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = capture_prepare, .trigger = capture_trigger, .pointer = capture_pointer, @@ -427,8 +387,8 @@ int snd_dice_create_pcm(struct snd_dice *dice) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = playback_hw_params, - .hw_free = playback_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = playback_prepare, .trigger = playback_trigger, .pointer = playback_pointer, From c7e68a697c7cd7fd25ee536d02a8dcf81a2e7d1c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 11 Jun 2019 19:09:07 +0200 Subject: [PATCH 330/626] ALSA: hda: fix a mask for unsolicited event tags Response tag only occupies 6 bits, not 7. This bug is harmless, since the value has just been shifted to the right by 26 bits, so this is only a cosmetic fix. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_jack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 74b46952fc98..60a548513c9d 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -563,7 +563,7 @@ static void call_jack_callback(struct hda_codec *codec, unsigned int res, void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) { struct hda_jack_tbl *event; - int tag = (res >> AC_UNSOL_RES_TAG_SHIFT) & 0x7f; + int tag = (res & AC_UNSOL_RES_TAG) >> AC_UNSOL_RES_TAG_SHIFT; event = snd_hda_jack_tbl_get_from_tag(codec, tag); if (!event) From 2e927ad7981db6765a2a0e8694371e0154b6e820 Mon Sep 17 00:00:00 2001 From: David Lin Date: Mon, 10 Jun 2019 11:05:23 +0800 Subject: [PATCH 331/626] ASoC: nau8822: support master mode The driver selects the proper BCLK divide through the BCLK and FS at the hardware parameter when the I2S master mode. Signed-off-by: David Lin Signed-off-by: John Hsu Signed-off-by: Mark Brown --- sound/soc/codecs/nau8822.c | 18 ++++++++++++++++++ sound/soc/codecs/nau8822.h | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index c6152a044416..78db3bd0b3bc 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -828,6 +828,24 @@ static int nau8822_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); int val_len = 0, val_rate = 0; + unsigned int ctrl_val, bclk_fs, bclk_div; + + /* make BCLK and LRC divide configuration if the codec as master. */ + snd_soc_component_read(component, NAU8822_REG_CLOCKING, &ctrl_val); + if (ctrl_val & NAU8822_CLK_MASTER) { + /* get the bclk and fs ratio */ + bclk_fs = snd_soc_params_to_bclk(params) / params_rate(params); + if (bclk_fs <= 32) + bclk_div = NAU8822_BCLKDIV_8; + else if (bclk_fs <= 64) + bclk_div = NAU8822_BCLKDIV_4; + else if (bclk_fs <= 128) + bclk_div = NAU8822_BCLKDIV_2; + else + return -EINVAL; + snd_soc_component_update_bits(component, NAU8822_REG_CLOCKING, + NAU8822_BCLKSEL_MASK, bclk_div); + } switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h index 9c552983a293..489191ff187e 100644 --- a/sound/soc/codecs/nau8822.h +++ b/sound/soc/codecs/nau8822.h @@ -107,10 +107,17 @@ /* NAU8822_REG_CLOCKING (0x6) */ #define NAU8822_CLKIOEN_MASK 0x1 +#define NAU8822_CLK_MASTER 0x1 +#define NAU8822_CLK_SLAVE 0x0 #define NAU8822_MCLKSEL_SFT 5 #define NAU8822_MCLKSEL_MASK (0x7 << 5) #define NAU8822_BCLKSEL_SFT 2 #define NAU8822_BCLKSEL_MASK (0x7 << 2) +#define NAU8822_BCLKDIV_1 (0x0 << 2) +#define NAU8822_BCLKDIV_2 (0x1 << 2) +#define NAU8822_BCLKDIV_4 (0x2 << 2) +#define NAU8822_BCLKDIV_8 (0x3 << 2) +#define NAU8822_BCLKDIV_16 (0x4 << 2) #define NAU8822_CLKM_MASK (0x1 << 8) #define NAU8822_CLKM_MCLK (0x0 << 8) #define NAU8822_CLKM_PLL (0x1 << 8) From b7e47f48f1197c24f5347327afc2a4f7f6da9ca5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 11 Jun 2019 15:29:40 +0300 Subject: [PATCH 332/626] bindings: sound: davinci-mcasp: Add support for optional auxclk-fs-ratio When McASP is bus master it's reference clock (AUXCLK) might not be a static clock, but running at a specific FS ratio. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/davinci-mcasp-audio.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index a58f79f5345c..c483dcec01f8 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -44,6 +44,9 @@ Optional properties: please refer to pinctrl-bindings.txt - fck_parent : Should contain a valid clock name which will be used as parent for the McASP fck +- auxclk-fs-ratio: When McASP is bus master indicates the ratio between AUCLK + and FS rate if applicable: + AUCLK rate = auxclk-fs-ratio * FS rate Optional GPIO support: If any McASP pin need to be used as GPIO then the McASP node must have: From 764958f2b5239cbf174e70cad4c3f19a8c1081ba Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 11 Jun 2019 15:29:41 +0300 Subject: [PATCH 333/626] ASoC: ti: davinci-mcasp: Support for auxclk-fs-ratio When McASP is bus master and it's AUXCLK clock is not static, but it is a multiple of the frame sync the constraint rules should take it account when validating possible stream formats. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 52 ++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 9fbc759fdefe..a8378d223a9e 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -100,6 +100,7 @@ struct davinci_mcasp { int sysclk_freq; bool bclk_master; + u32 auxclk_fs_ratio; unsigned long pdir; /* Pin direction bitfield */ @@ -1064,13 +1065,13 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, } static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp, + unsigned int sysclk_freq, unsigned int bclk_freq, bool set) { - int error_ppm; - unsigned int sysclk_freq = mcasp->sysclk_freq; u32 reg = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG); int div = sysclk_freq / bclk_freq; int rem = sysclk_freq % bclk_freq; + int error_ppm; int aux_div = 1; if (div > (ACLKXDIV_MASK + 1)) { @@ -1175,7 +1176,8 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, if (mcasp->slot_width) sbits = mcasp->slot_width; - davinci_mcasp_calc_clk_div(mcasp, rate * sbits * slots, true); + davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq, + rate * sbits * slots, true); } ret = mcasp_common_hw_param(mcasp, substream->stream, @@ -1282,12 +1284,19 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params, for (i = 0; i < ARRAY_SIZE(davinci_mcasp_dai_rates); i++) { if (snd_interval_test(ri, davinci_mcasp_dai_rates[i])) { - uint bclk_freq = sbits*slots* - davinci_mcasp_dai_rates[i]; + uint bclk_freq = sbits * slots * + davinci_mcasp_dai_rates[i]; + unsigned int sysclk_freq; int ppm; - ppm = davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, - false); + if (rd->mcasp->auxclk_fs_ratio) + sysclk_freq = davinci_mcasp_dai_rates[i] * + rd->mcasp->auxclk_fs_ratio; + else + sysclk_freq = rd->mcasp->sysclk_freq; + + ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq, + bclk_freq, false); if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { if (range.empty) { range.min = davinci_mcasp_dai_rates[i]; @@ -1321,12 +1330,19 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params, for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { if (snd_mask_test(fmt, i)) { uint sbits = snd_pcm_format_width(i); + unsigned int sysclk_freq; int ppm; + if (rd->mcasp->auxclk_fs_ratio) + sysclk_freq = rate * + rd->mcasp->auxclk_fs_ratio; + else + sysclk_freq = rd->mcasp->sysclk_freq; + if (rd->mcasp->slot_width) sbits = rd->mcasp->slot_width; - ppm = davinci_mcasp_calc_clk_div(rd->mcasp, + ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq, sbits * slots * rate, false); if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { @@ -1991,6 +2007,22 @@ static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) } #endif /* CONFIG_GPIOLIB */ +static int davinci_mcasp_get_dt_params(struct davinci_mcasp *mcasp) +{ + struct device_node *np = mcasp->dev->of_node; + int ret; + u32 val; + + if (!np) + return 0; + + ret = of_property_read_u32(np, "auxclk-fs-ratio", &val); + if (ret >= 0) + mcasp->auxclk_fs_ratio = val; + + return 0; +} + static int davinci_mcasp_probe(struct platform_device *pdev) { struct snd_dmaengine_dai_dma_data *dma_data; @@ -2224,6 +2256,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (ret) goto err; + ret = davinci_mcasp_get_dt_params(mcasp); + if (ret) + return -EINVAL; + ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1); From ac2888b958f217be15d6afb966df48a313f2d87a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:04 +0900 Subject: [PATCH 334/626] ALSA: bebob: configure sampling transfer frequency in pcm.hw_params callback This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. At present, several operations are done in pcm.prepare callback. To reduce load of the callback, This commit splits out an operation to set sampling transfer frequency in pcm.hw_params callback. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.h | 3 +- sound/firewire/bebob/bebob_midi.c | 22 ++- sound/firewire/bebob/bebob_pcm.c | 22 ++- sound/firewire/bebob/bebob_stream.c | 220 ++++++++++++++-------------- 4 files changed, 140 insertions(+), 127 deletions(-) diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index df1b1e94c43c..c30ed44aced9 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -218,7 +218,8 @@ int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, enum snd_bebob_clock_type *src); int snd_bebob_stream_discover(struct snd_bebob *bebob); int snd_bebob_stream_init_duplex(struct snd_bebob *bebob); -int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate); +int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate); +int snd_bebob_stream_start_duplex(struct snd_bebob *bebob); void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob); void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob); diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index 3befa3eca6ef..e2d3cad39d28 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -15,15 +15,18 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) err = snd_bebob_stream_lock_try(bebob); if (err < 0) - goto end; + return err; mutex_lock(&bebob->mutex); - bebob->substreams_counter++; - err = snd_bebob_stream_start_duplex(bebob, 0); + err = snd_bebob_stream_reserve_duplex(bebob, 0); + if (err >= 0) { + ++bebob->substreams_counter; + err = snd_bebob_stream_start_duplex(bebob); + } mutex_unlock(&bebob->mutex); if (err < 0) snd_bebob_stream_lock_release(bebob); -end: + return err; } @@ -34,15 +37,18 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) err = snd_bebob_stream_lock_try(bebob); if (err < 0) - goto end; + return err; mutex_lock(&bebob->mutex); - bebob->substreams_counter++; - err = snd_bebob_stream_start_duplex(bebob, 0); + err = snd_bebob_stream_reserve_duplex(bebob, 0); + if (err >= 0) { + ++bebob->substreams_counter; + err = snd_bebob_stream_start_duplex(bebob); + } mutex_unlock(&bebob->mutex); if (err < 0) snd_bebob_stream_lock_release(bebob); -end: + return err; } diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index ea9b86450580..71b6ede31bb2 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -198,12 +198,16 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&bebob->mutex); - bebob->substreams_counter++; + err = snd_bebob_stream_reserve_duplex(bebob, rate); + if (err >= 0) + ++bebob->substreams_counter; mutex_unlock(&bebob->mutex); } - return 0; + return err; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, @@ -218,12 +222,16 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&bebob->mutex); - bebob->substreams_counter++; + err = snd_bebob_stream_reserve_duplex(bebob, rate); + if (err >= 0) + ++bebob->substreams_counter; mutex_unlock(&bebob->mutex); } - return 0; + return err; } static int @@ -261,10 +269,9 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; - err = snd_bebob_stream_start_duplex(bebob, runtime->rate); + err = snd_bebob_stream_start_duplex(bebob); if (err >= 0) amdtp_stream_pcm_prepare(&bebob->tx_stream); @@ -274,10 +281,9 @@ static int pcm_playback_prepare(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; - err = snd_bebob_stream_start_duplex(bebob, runtime->rate); + err = snd_bebob_stream_start_duplex(bebob); if (err >= 0) amdtp_stream_pcm_prepare(&bebob->rx_stream); diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 4d3034a68bdf..fcc93156d0b7 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -418,49 +418,28 @@ check_connection_used_by_others(struct snd_bebob *bebob, struct amdtp_stream *s) return err; } -static int -make_both_connections(struct snd_bebob *bebob, unsigned int rate) +static int make_both_connections(struct snd_bebob *bebob) { - int index, pcm_channels, midi_channels, err = 0; + int err = 0; if (bebob->connected) - goto end; + return 0; - /* confirm params for both streams */ - err = get_formation_index(rate, &index); - if (err < 0) - goto end; - pcm_channels = bebob->tx_stream_formations[index].pcm; - midi_channels = bebob->tx_stream_formations[index].midi; - err = amdtp_am824_set_parameters(&bebob->tx_stream, rate, - pcm_channels, midi_channels * 8, - false); - if (err < 0) - goto end; - - pcm_channels = bebob->rx_stream_formations[index].pcm; - midi_channels = bebob->rx_stream_formations[index].midi; - err = amdtp_am824_set_parameters(&bebob->rx_stream, rate, - pcm_channels, midi_channels * 8, - false); - if (err < 0) - goto end; - - /* establish connections for both streams */ err = cmp_connection_establish(&bebob->out_conn, amdtp_stream_get_max_payload(&bebob->tx_stream)); if (err < 0) - goto end; + return err; + err = cmp_connection_establish(&bebob->in_conn, amdtp_stream_get_max_payload(&bebob->rx_stream)); if (err < 0) { cmp_connection_break(&bebob->out_conn); - goto end; + return err; } bebob->connected = true; -end: - return err; + + return 0; } static void @@ -484,8 +463,7 @@ destroy_both_connections(struct snd_bebob *bebob) } static int -start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream, - unsigned int rate) +start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) { struct cmp_connection *conn; int err = 0; @@ -555,132 +533,154 @@ end: return err; } -int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) +static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, + unsigned int rate, unsigned int index) +{ + struct snd_bebob_stream_formation *formation; + + if (stream == &bebob->tx_stream) + formation = bebob->tx_stream_formations + index; + else + formation = bebob->rx_stream_formations + index; + + return amdtp_am824_set_parameters(stream, rate, formation->pcm, + formation->midi, false); +} + +int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) { - const struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; unsigned int curr_rate; - int err = 0; + int err; - /* Need no substreams */ - if (bebob->substreams_counter == 0) - goto end; - - /* - * Considering JACK/FFADO streaming: - * TODO: This can be removed hwdep functionality becomes popular. - */ + // Considering JACK/FFADO streaming: + // TODO: This can be removed hwdep functionality becomes popular. err = check_connection_used_by_others(bebob, &bebob->rx_stream); if (err < 0) - goto end; + return err; - /* - * packet queueing error or detecting discontinuity - * - * At bus reset, connections should not be broken here. So streams need - * to be re-started. This is a reason to use SKIP_INIT_DBC_CHECK flag. - */ - if (amdtp_streaming_error(&bebob->rx_stream)) - amdtp_stream_stop(&bebob->rx_stream); - if (amdtp_streaming_error(&bebob->tx_stream)) - amdtp_stream_stop(&bebob->tx_stream); - if (!amdtp_stream_running(&bebob->rx_stream) && - !amdtp_stream_running(&bebob->tx_stream)) - break_both_connections(bebob); - - /* stop streams if rate is different */ - err = rate_spec->get(bebob, &curr_rate); - if (err < 0) { - dev_err(&bebob->unit->device, - "fail to get sampling rate: %d\n", err); - goto end; - } + err = bebob->spec->rate->get(bebob, &curr_rate); + if (err < 0) + return err; if (rate == 0) rate = curr_rate; - if (rate != curr_rate) { - amdtp_stream_stop(&bebob->rx_stream); + if (curr_rate != rate) { amdtp_stream_stop(&bebob->tx_stream); + amdtp_stream_stop(&bebob->rx_stream); + break_both_connections(bebob); } - /* master should be always running */ - if (!amdtp_stream_running(&bebob->rx_stream)) { - /* - * NOTE: - * If establishing connections at first, Yamaha GO46 - * (and maybe Terratec X24) don't generate sound. - * - * For firmware customized by M-Audio, refer to next NOTE. - */ - if (bebob->maudio_special_quirk == NULL) { - err = rate_spec->set(bebob, rate); - if (err < 0) { - dev_err(&bebob->unit->device, - "fail to set sampling rate: %d\n", - err); - goto end; - } + if (bebob->substreams_counter == 0 || curr_rate != rate) { + unsigned int index; + + // NOTE: + // If establishing connections at first, Yamaha GO46 + // (and maybe Terratec X24) don't generate sound. + // + // For firmware customized by M-Audio, refer to next NOTE. + err = bebob->spec->rate->set(bebob, rate); + if (err < 0) { + dev_err(&bebob->unit->device, + "fail to set sampling rate: %d\n", + err); + return err; } - err = make_both_connections(bebob, rate); + err = get_formation_index(rate, &index); if (err < 0) - goto end; + return err; - err = start_stream(bebob, &bebob->rx_stream, rate); + err = keep_resources(bebob, &bebob->tx_stream, rate, index); + if (err < 0) + return err; + + err = keep_resources(bebob, &bebob->rx_stream, rate, index); + if (err < 0) + return err; + } + + return 0; +} + +int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) +{ + int err; + + // Need no substreams. + if (bebob->substreams_counter == 0) + return -EIO; + + // packet queueing error or detecting discontinuity + if (amdtp_streaming_error(&bebob->rx_stream) || + amdtp_streaming_error(&bebob->tx_stream)) { + amdtp_stream_stop(&bebob->rx_stream); + amdtp_stream_stop(&bebob->tx_stream); + + break_both_connections(bebob); + } + + if (!amdtp_stream_running(&bebob->rx_stream)) { + unsigned int curr_rate; + + if (bebob->maudio_special_quirk) { + err = bebob->spec->rate->get(bebob, &curr_rate); + if (err < 0) + return err; + } + + err = make_both_connections(bebob); + if (err < 0) + return err; + + err = start_stream(bebob, &bebob->rx_stream); if (err < 0) { dev_err(&bebob->unit->device, "fail to run AMDTP master stream:%d\n", err); - break_both_connections(bebob); - goto end; + goto error; } - /* - * NOTE: - * The firmware customized by M-Audio uses these commands to - * start transmitting stream. This is not usual way. - */ - if (bebob->maudio_special_quirk != NULL) { - err = rate_spec->set(bebob, rate); + // NOTE: + // The firmware customized by M-Audio uses these commands to + // start transmitting stream. This is not usual way. + if (bebob->maudio_special_quirk) { + err = bebob->spec->rate->set(bebob, curr_rate); if (err < 0) { dev_err(&bebob->unit->device, "fail to ensure sampling rate: %d\n", err); - amdtp_stream_stop(&bebob->rx_stream); - break_both_connections(bebob); - goto end; + goto error; } } - /* wait first callback */ if (!amdtp_stream_wait_callback(&bebob->rx_stream, CALLBACK_TIMEOUT)) { amdtp_stream_stop(&bebob->rx_stream); break_both_connections(bebob); err = -ETIMEDOUT; - goto end; + goto error; } } - /* start slave if needed */ if (!amdtp_stream_running(&bebob->tx_stream)) { - err = start_stream(bebob, &bebob->tx_stream, rate); + err = start_stream(bebob, &bebob->tx_stream); if (err < 0) { dev_err(&bebob->unit->device, "fail to run AMDTP slave stream:%d\n", err); - amdtp_stream_stop(&bebob->rx_stream); - break_both_connections(bebob); - goto end; + goto error; } - /* wait first callback */ if (!amdtp_stream_wait_callback(&bebob->tx_stream, CALLBACK_TIMEOUT)) { - amdtp_stream_stop(&bebob->tx_stream); - amdtp_stream_stop(&bebob->rx_stream); - break_both_connections(bebob); err = -ETIMEDOUT; + goto error; } } -end: + + return 0; +error: + amdtp_stream_stop(&bebob->tx_stream); + amdtp_stream_stop(&bebob->rx_stream); + break_both_connections(bebob); return err; } From 83122f85d4d87885a379a7f71cd6688b1a38d4e1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:05 +0900 Subject: [PATCH 335/626] ALSA: bebob: don't set XRUN in stop streaming When stopping packet streaming, no need to stop PCM substream with XRUN state. This commit suppresses it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_stream.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index fcc93156d0b7..d6e7f13ef42d 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -687,10 +687,7 @@ error: void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) { if (bebob->substreams_counter == 0) { - amdtp_stream_pcm_abort(&bebob->rx_stream); amdtp_stream_stop(&bebob->rx_stream); - - amdtp_stream_pcm_abort(&bebob->tx_stream); amdtp_stream_stop(&bebob->tx_stream); break_both_connections(bebob); From 87a23092dd971b960f9065dbc0cc48be31400326 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:06 +0900 Subject: [PATCH 336/626] ALSA: bebob: obsolete useless member of private structure The private structure of this driver has 'connected' member but nowadays it's useless. This commit removes it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.h | 2 -- sound/firewire/bebob/bebob_stream.c | 7 ------- 2 files changed, 9 deletions(-) diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index c30ed44aced9..20ed2dbd8d61 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -93,8 +93,6 @@ struct snd_bebob { unsigned int midi_input_ports; unsigned int midi_output_ports; - bool connected; - struct amdtp_stream tx_stream; struct amdtp_stream rx_stream; struct cmp_connection out_conn; diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index d6e7f13ef42d..c3cc31df49e0 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -422,9 +422,6 @@ static int make_both_connections(struct snd_bebob *bebob) { int err = 0; - if (bebob->connected) - return 0; - err = cmp_connection_establish(&bebob->out_conn, amdtp_stream_get_max_payload(&bebob->tx_stream)); if (err < 0) @@ -437,8 +434,6 @@ static int make_both_connections(struct snd_bebob *bebob) return err; } - bebob->connected = true; - return 0; } @@ -448,8 +443,6 @@ break_both_connections(struct snd_bebob *bebob) cmp_connection_break(&bebob->in_conn); cmp_connection_break(&bebob->out_conn); - bebob->connected = false; - /* These models seems to be in transition state for a longer time. */ if (bebob->maudio_special_quirk != NULL) msleep(200); From 33e41a5ce59ad34c822228d3811ba3785f1a97a2 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:07 +0900 Subject: [PATCH 337/626] ALSA: bebob: code refactoring to initialize/destroy stream data This commit changes helper functions to initialize/destroy stream data so that it has an argument for direction. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_stream.c | 127 ++++++++++++++-------------- 1 file changed, 64 insertions(+), 63 deletions(-) diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index c3cc31df49e0..6aab3dc99bef 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -376,24 +376,6 @@ end: return err; } -static int -init_both_connections(struct snd_bebob *bebob) -{ - int err; - - err = cmp_connection_init(&bebob->in_conn, - bebob->unit, CMP_INPUT, 0); - if (err < 0) - goto end; - - err = cmp_connection_init(&bebob->out_conn, - bebob->unit, CMP_OUTPUT, 0); - if (err < 0) - cmp_connection_destroy(&bebob->in_conn); -end: - return err; -} - static int check_connection_used_by_others(struct snd_bebob *bebob, struct amdtp_stream *s) { @@ -448,13 +430,6 @@ break_both_connections(struct snd_bebob *bebob) msleep(200); } -static void -destroy_both_connections(struct snd_bebob *bebob) -{ - cmp_connection_destroy(&bebob->in_conn); - cmp_connection_destroy(&bebob->out_conn); -} - static int start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) { @@ -481,49 +456,77 @@ end: return err; } +static int init_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) +{ + enum amdtp_stream_direction dir_stream; + struct cmp_connection *conn; + enum cmp_direction dir_conn; + int err; + + if (stream == &bebob->tx_stream) { + dir_stream = AMDTP_IN_STREAM; + conn = &bebob->out_conn; + dir_conn = CMP_OUTPUT; + } else { + dir_stream = AMDTP_OUT_STREAM; + conn = &bebob->in_conn; + dir_conn = CMP_INPUT; + } + + err = cmp_connection_init(conn, bebob->unit, dir_conn, 0); + if (err < 0) + return err; + + err = amdtp_am824_init(stream, bebob->unit, dir_stream, CIP_BLOCKING); + if (err < 0) { + cmp_connection_destroy(conn); + return err; + } + + if (stream == &bebob->tx_stream) { + // BeBoB v3 transfers packets with these qurks: + // - In the beginning of streaming, the value of dbc is + // incremented even if no data blocks are transferred. + // - The value of dbc is reset suddenly. + if (bebob->version > 2) + bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | + CIP_SKIP_DBC_ZERO_CHECK; + + // At high sampling rate, M-Audio special firmware transmits + // empty packet with the value of dbc incremented by 8 but the + // others are valid to IEC 61883-1. + if (bebob->maudio_special_quirk) + bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; + } + + return 0; +} + +static void destroy_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) +{ + amdtp_stream_destroy(stream); + + if (stream == &bebob->tx_stream) + cmp_connection_destroy(&bebob->out_conn); + else + cmp_connection_destroy(&bebob->in_conn); +} + int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) { int err; - err = init_both_connections(bebob); + err = init_stream(bebob, &bebob->tx_stream); if (err < 0) - goto end; + return err; - err = amdtp_am824_init(&bebob->tx_stream, bebob->unit, - AMDTP_IN_STREAM, CIP_BLOCKING); + err = init_stream(bebob, &bebob->rx_stream); if (err < 0) { - amdtp_stream_destroy(&bebob->tx_stream); - destroy_both_connections(bebob); - goto end; + destroy_stream(bebob, &bebob->tx_stream); + return err; } - /* - * BeBoB v3 transfers packets with these qurks: - * - In the beginning of streaming, the value of dbc is incremented - * even if no data blocks are transferred. - * - The value of dbc is reset suddenly. - */ - if (bebob->version > 2) - bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | - CIP_SKIP_DBC_ZERO_CHECK; - - /* - * At high sampling rate, M-Audio special firmware transmits empty - * packet with the value of dbc incremented by 8 but the others are - * valid to IEC 61883-1. - */ - if (bebob->maudio_special_quirk) - bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; - - err = amdtp_am824_init(&bebob->rx_stream, bebob->unit, - AMDTP_OUT_STREAM, CIP_BLOCKING); - if (err < 0) { - amdtp_stream_destroy(&bebob->tx_stream); - amdtp_stream_destroy(&bebob->rx_stream); - destroy_both_connections(bebob); - } -end: - return err; + return 0; } static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, @@ -693,10 +696,8 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) */ void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) { - amdtp_stream_destroy(&bebob->rx_stream); - amdtp_stream_destroy(&bebob->tx_stream); - - destroy_both_connections(bebob); + destroy_stream(bebob, &bebob->tx_stream); + destroy_stream(bebob, &bebob->rx_stream); } /* From 1dc5921082d48dc53e48e88ae2f9a24b9737307d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:08 +0900 Subject: [PATCH 338/626] ALSA: fireworks: unify substream counter This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. It's inconvenient to handle two isochronous context separately each other. This commit unifies the counters to handle the two at the same time. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks.h | 3 +-- sound/firewire/fireworks/fireworks_midi.c | 8 +++--- sound/firewire/fireworks/fireworks_pcm.c | 8 +++--- sound/firewire/fireworks/fireworks_stream.c | 27 ++++++++------------- 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index 9b19c7f05d57..42a73038ba4d 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h @@ -89,8 +89,7 @@ struct snd_efw { struct amdtp_stream rx_stream; struct cmp_connection out_conn; struct cmp_connection in_conn; - unsigned int capture_substreams; - unsigned int playback_substreams; + unsigned int substreams_counter; /* hardware metering parameters */ unsigned int phys_out; diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c index f5da2cd4ce42..7e78cdfe699e 100644 --- a/sound/firewire/fireworks/fireworks_midi.c +++ b/sound/firewire/fireworks/fireworks_midi.c @@ -18,7 +18,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) goto end; mutex_lock(&efw->mutex); - efw->capture_substreams++; + ++efw->substreams_counter; err = snd_efw_stream_start_duplex(efw, 0); mutex_unlock(&efw->mutex); if (err < 0) @@ -38,7 +38,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) goto end; mutex_lock(&efw->mutex); - efw->playback_substreams++; + ++efw->substreams_counter; err = snd_efw_stream_start_duplex(efw, 0); mutex_unlock(&efw->mutex); if (err < 0) @@ -52,7 +52,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) struct snd_efw *efw = substream->rmidi->private_data; mutex_lock(&efw->mutex); - efw->capture_substreams--; + --efw->substreams_counter; snd_efw_stream_stop_duplex(efw); mutex_unlock(&efw->mutex); @@ -65,7 +65,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) struct snd_efw *efw = substream->rmidi->private_data; mutex_lock(&efw->mutex); - efw->playback_substreams--; + --efw->substreams_counter; snd_efw_stream_stop_duplex(efw); mutex_unlock(&efw->mutex); diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index aed566d82726..a66f6a381dac 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -232,7 +232,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&efw->mutex); - efw->capture_substreams++; + ++efw->substreams_counter; mutex_unlock(&efw->mutex); } @@ -251,7 +251,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&efw->mutex); - efw->playback_substreams++; + ++efw->substreams_counter; mutex_unlock(&efw->mutex); } @@ -264,7 +264,7 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { mutex_lock(&efw->mutex); - efw->capture_substreams--; + --efw->substreams_counter; mutex_unlock(&efw->mutex); } @@ -278,7 +278,7 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { mutex_lock(&efw->mutex); - efw->playback_substreams--; + --efw->substreams_counter; mutex_unlock(&efw->mutex); } diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 74e122e6e68a..2df39befcde0 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -194,9 +194,9 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) unsigned int curr_rate; int err = 0; - /* Need no substreams */ - if (efw->playback_substreams == 0 && efw->capture_substreams == 0) - goto end; + // Need no substreams. + if (efw->substreams_counter == 0) + return -EIO; /* * Considering JACK/FFADO streaming: @@ -206,19 +206,15 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) if (err < 0) goto end; - /* packet queueing error */ - if (amdtp_streaming_error(&efw->tx_stream)) - stop_stream(efw, &efw->tx_stream); - if (amdtp_streaming_error(&efw->rx_stream)) - stop_stream(efw, &efw->rx_stream); - /* stop streams if rate is different */ err = snd_efw_command_get_sampling_rate(efw, &curr_rate); if (err < 0) goto end; if (rate == 0) rate = curr_rate; - if (rate != curr_rate) { + if (rate != curr_rate || + amdtp_streaming_error(&efw->tx_stream) || + amdtp_streaming_error(&efw->rx_stream)) { stop_stream(efw, &efw->tx_stream); stop_stream(efw, &efw->rx_stream); } @@ -237,13 +233,12 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) } } - /* start slave if needed */ - if (efw->capture_substreams > 0 && - !amdtp_stream_running(&efw->tx_stream)) { + if (!amdtp_stream_running(&efw->tx_stream)) { err = start_stream(efw, &efw->tx_stream, rate); if (err < 0) { dev_err(&efw->unit->device, "fail to start AMDTP slave stream:%d\n", err); + stop_stream(efw, &efw->tx_stream); stop_stream(efw, &efw->rx_stream); } } @@ -253,11 +248,9 @@ end: void snd_efw_stream_stop_duplex(struct snd_efw *efw) { - if (efw->capture_substreams == 0) { + if (efw->substreams_counter == 0) { stop_stream(efw, &efw->tx_stream); - - if (efw->playback_substreams == 0) - stop_stream(efw, &efw->rx_stream); + stop_stream(efw, &efw->rx_stream); } } From add147ad556cce588d1a714a6df4c4e556a6cb2f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:09 +0900 Subject: [PATCH 339/626] ALSA: fireworks: code refactoring for rawmidi.open/close Two sets of callbacks for rawmidi.open/close but they have the same codes. This commit unifies each of the callbacks. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_midi.c | 45 +++-------------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c index 7e78cdfe699e..ee5dc7be70b6 100644 --- a/sound/firewire/fireworks/fireworks_midi.c +++ b/sound/firewire/fireworks/fireworks_midi.c @@ -8,27 +8,7 @@ */ #include "fireworks.h" -static int midi_capture_open(struct snd_rawmidi_substream *substream) -{ - struct snd_efw *efw = substream->rmidi->private_data; - int err; - - err = snd_efw_stream_lock_try(efw); - if (err < 0) - goto end; - - mutex_lock(&efw->mutex); - ++efw->substreams_counter; - err = snd_efw_stream_start_duplex(efw, 0); - mutex_unlock(&efw->mutex); - if (err < 0) - snd_efw_stream_lock_release(efw); - -end: - return err; -} - -static int midi_playback_open(struct snd_rawmidi_substream *substream) +static int midi_open(struct snd_rawmidi_substream *substream) { struct snd_efw *efw = substream->rmidi->private_data; int err; @@ -47,20 +27,7 @@ end: return err; } -static int midi_capture_close(struct snd_rawmidi_substream *substream) -{ - struct snd_efw *efw = substream->rmidi->private_data; - - mutex_lock(&efw->mutex); - --efw->substreams_counter; - snd_efw_stream_stop_duplex(efw); - mutex_unlock(&efw->mutex); - - snd_efw_stream_lock_release(efw); - return 0; -} - -static int midi_playback_close(struct snd_rawmidi_substream *substream) +static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_efw *efw = substream->rmidi->private_data; @@ -121,13 +88,13 @@ static void set_midi_substream_names(struct snd_efw *efw, int snd_efw_create_midi_devices(struct snd_efw *efw) { static const struct snd_rawmidi_ops capture_ops = { - .open = midi_capture_open, - .close = midi_capture_close, + .open = midi_open, + .close = midi_close, .trigger = midi_capture_trigger, }; static const struct snd_rawmidi_ops playback_ops = { - .open = midi_playback_open, - .close = midi_playback_close, + .open = midi_open, + .close = midi_close, .trigger = midi_playback_trigger, }; struct snd_rawmidi *rmidi; From fb56eb73c6266164e4b06c9eca9716348420dbf1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:10 +0900 Subject: [PATCH 340/626] ALSA: fireworks: code refactoring for pcm.hw_params/hw_free Two sets of callbacks for pcm.hw_params/hw_free but they have the same codes. This commit unifies each of the callbacks. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_pcm.c | 45 ++++-------------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index a66f6a381dac..398a6ad04c5f 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -219,7 +219,7 @@ static int pcm_close(struct snd_pcm_substream *substream) return 0; } -static int pcm_capture_hw_params(struct snd_pcm_substream *substream, +static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_efw *efw = substream->private_data; @@ -238,41 +238,8 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, return 0; } -static int pcm_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_efw *efw = substream->private_data; - int err; - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { - mutex_lock(&efw->mutex); - ++efw->substreams_counter; - mutex_unlock(&efw->mutex); - } - - return 0; -} - -static int pcm_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_efw *efw = substream->private_data; - - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { - mutex_lock(&efw->mutex); - --efw->substreams_counter; - mutex_unlock(&efw->mutex); - } - - snd_efw_stream_stop_duplex(efw); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} -static int pcm_playback_hw_free(struct snd_pcm_substream *substream) +static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; @@ -378,8 +345,8 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_capture_hw_params, - .hw_free = pcm_capture_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, @@ -390,8 +357,8 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_playback_hw_params, - .hw_free = pcm_playback_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, From 3d7250667ea96e7f9738caa6d5af85d87982066e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:11 +0900 Subject: [PATCH 341/626] ALSA: fireworks: configure sampling transfer frequency in pcm.hw_params callback This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. At present, several operations are done in pcm.prepare callback. To reduce load of the callback, This commit splits out an operation to set sampling transfer frequency in pcm.hw_params callback. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks.h | 3 +- sound/firewire/fireworks/fireworks_midi.c | 7 ++- sound/firewire/fireworks/fireworks_pcm.c | 14 +++-- sound/firewire/fireworks/fireworks_stream.c | 69 +++++++++++++-------- 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index 42a73038ba4d..0c1802aa7923 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h @@ -206,7 +206,8 @@ int snd_efw_command_get_sampling_rate(struct snd_efw *efw, unsigned int *rate); int snd_efw_command_set_sampling_rate(struct snd_efw *efw, unsigned int rate); int snd_efw_stream_init_duplex(struct snd_efw *efw); -int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate); +int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate); +int snd_efw_stream_start_duplex(struct snd_efw *efw); void snd_efw_stream_stop_duplex(struct snd_efw *efw); void snd_efw_stream_update_duplex(struct snd_efw *efw); void snd_efw_stream_destroy_duplex(struct snd_efw *efw); diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c index ee5dc7be70b6..6d3d942e2dce 100644 --- a/sound/firewire/fireworks/fireworks_midi.c +++ b/sound/firewire/fireworks/fireworks_midi.c @@ -18,8 +18,11 @@ static int midi_open(struct snd_rawmidi_substream *substream) goto end; mutex_lock(&efw->mutex); - ++efw->substreams_counter; - err = snd_efw_stream_start_duplex(efw, 0); + err = snd_efw_stream_reserve_duplex(efw, 0); + if (err >= 0) { + ++efw->substreams_counter; + err = snd_efw_stream_start_duplex(efw); + } mutex_unlock(&efw->mutex); if (err < 0) snd_efw_stream_lock_release(efw); diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 398a6ad04c5f..287fc05d5917 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -231,12 +231,16 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&efw->mutex); - ++efw->substreams_counter; + err = snd_efw_stream_reserve_duplex(efw, rate); + if (err >= 0) + ++efw->substreams_counter; mutex_unlock(&efw->mutex); } - return 0; + return err; } static int pcm_hw_free(struct snd_pcm_substream *substream) @@ -257,10 +261,9 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) static int pcm_capture_prepare(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; - err = snd_efw_stream_start_duplex(efw, runtime->rate); + err = snd_efw_stream_start_duplex(efw); if (err >= 0) amdtp_stream_pcm_prepare(&efw->tx_stream); @@ -269,10 +272,9 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) static int pcm_playback_prepare(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; - err = snd_efw_stream_start_duplex(efw, runtime->rate); + err = snd_efw_stream_start_duplex(efw); if (err >= 0) amdtp_stream_pcm_prepare(&efw->rx_stream); diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 2df39befcde0..e1ebead583e9 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -189,47 +189,63 @@ end: return err; } -int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) +int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) { unsigned int curr_rate; + int err; + + // Considering JACK/FFADO streaming: + // TODO: This can be removed hwdep functionality becomes popular. + err = check_connection_used_by_others(efw, &efw->rx_stream); + if (err < 0) + return err; + + // stop streams if rate is different. + err = snd_efw_command_get_sampling_rate(efw, &curr_rate); + if (err < 0) + return err; + if (rate == 0) + rate = curr_rate; + if (rate != curr_rate) { + stop_stream(efw, &efw->tx_stream); + stop_stream(efw, &efw->rx_stream); + } + + if (efw->substreams_counter == 0 || rate != curr_rate) { + err = snd_efw_command_set_sampling_rate(efw, rate); + if (err < 0) + return err; + } + + return 0; +} + +int snd_efw_stream_start_duplex(struct snd_efw *efw) +{ + unsigned int rate; int err = 0; // Need no substreams. if (efw->substreams_counter == 0) return -EIO; - /* - * Considering JACK/FFADO streaming: - * TODO: This can be removed hwdep functionality becomes popular. - */ - err = check_connection_used_by_others(efw, &efw->rx_stream); + err = snd_efw_command_get_sampling_rate(efw, &rate); if (err < 0) - goto end; + return err; - /* stop streams if rate is different */ - err = snd_efw_command_get_sampling_rate(efw, &curr_rate); - if (err < 0) - goto end; - if (rate == 0) - rate = curr_rate; - if (rate != curr_rate || - amdtp_streaming_error(&efw->tx_stream) || - amdtp_streaming_error(&efw->rx_stream)) { - stop_stream(efw, &efw->tx_stream); + if (amdtp_streaming_error(&efw->rx_stream) || + amdtp_streaming_error(&efw->tx_stream)) { stop_stream(efw, &efw->rx_stream); + stop_stream(efw, &efw->tx_stream); } /* master should be always running */ if (!amdtp_stream_running(&efw->rx_stream)) { - err = snd_efw_command_set_sampling_rate(efw, rate); - if (err < 0) - goto end; - err = start_stream(efw, &efw->rx_stream, rate); if (err < 0) { dev_err(&efw->unit->device, "fail to start AMDTP master stream:%d\n", err); - goto end; + goto error; } } @@ -238,11 +254,14 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) if (err < 0) { dev_err(&efw->unit->device, "fail to start AMDTP slave stream:%d\n", err); - stop_stream(efw, &efw->tx_stream); - stop_stream(efw, &efw->rx_stream); + goto error; } } -end: + + return 0; +error: + stop_stream(efw, &efw->rx_stream); + stop_stream(efw, &efw->tx_stream); return err; } From 206cf896d6e9024dbdf5722c4676f2e671191b97 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:12 +0900 Subject: [PATCH 342/626] ALSA: fireworks: configure stream parameters in pcm.hw_params callback This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. This commit splits out an operation to configure stream parameters into pcm.hw_params callback. In pcm.prepare callback, establishing connections and start isochronous contexts. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_stream.c | 82 ++++++++++++--------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index e1ebead583e9..1abc15760513 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -52,54 +52,38 @@ stop_stream(struct snd_efw *efw, struct amdtp_stream *stream) cmp_connection_break(&efw->in_conn); } -static int -start_stream(struct snd_efw *efw, struct amdtp_stream *stream, - unsigned int sampling_rate) +static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, + unsigned int rate) { struct cmp_connection *conn; - unsigned int mode, pcm_channels, midi_ports; int err; - err = snd_efw_get_multiplier_mode(sampling_rate, &mode); - if (err < 0) - goto end; - if (stream == &efw->tx_stream) { + if (stream == &efw->tx_stream) conn = &efw->out_conn; - pcm_channels = efw->pcm_capture_channels[mode]; - midi_ports = efw->midi_out_ports; - } else { + else conn = &efw->in_conn; - pcm_channels = efw->pcm_playback_channels[mode]; - midi_ports = efw->midi_in_ports; - } - err = amdtp_am824_set_parameters(stream, sampling_rate, - pcm_channels, midi_ports, false); - if (err < 0) - goto end; - - /* establish connection via CMP */ + // Establish connection via CMP. err = cmp_connection_establish(conn, - amdtp_stream_get_max_payload(stream)); + amdtp_stream_get_max_payload(stream)); if (err < 0) - goto end; + return err; - /* start amdtp stream */ - err = amdtp_stream_start(stream, - conn->resources.channel, - conn->speed); + // Start amdtp stream. + err = amdtp_stream_start(stream, conn->resources.channel, conn->speed); if (err < 0) { - stop_stream(efw, stream); - goto end; + cmp_connection_break(conn); + return err; } - /* wait first callback */ + // Wait first callback. if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { - stop_stream(efw, stream); - err = -ETIMEDOUT; + amdtp_stream_stop(stream); + cmp_connection_break(conn); + return -ETIMEDOUT; } -end: - return err; + + return 0; } /* @@ -189,6 +173,24 @@ end: return err; } +static int keep_resources(struct snd_efw *efw, struct amdtp_stream *stream, + unsigned int rate, unsigned int mode) +{ + unsigned int pcm_channels; + unsigned int midi_ports; + + if (stream == &efw->tx_stream) { + pcm_channels = efw->pcm_capture_channels[mode]; + midi_ports = efw->midi_out_ports; + } else { + pcm_channels = efw->pcm_playback_channels[mode]; + midi_ports = efw->midi_in_ports; + } + + return amdtp_am824_set_parameters(stream, rate, pcm_channels, + midi_ports, false); +} + int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) { unsigned int curr_rate; @@ -212,9 +214,23 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) } if (efw->substreams_counter == 0 || rate != curr_rate) { + unsigned int mode; + err = snd_efw_command_set_sampling_rate(efw, rate); if (err < 0) return err; + + err = snd_efw_get_multiplier_mode(rate, &mode); + if (err < 0) + return err; + + err = keep_resources(efw, &efw->tx_stream, rate, mode); + if (err < 0) + return err; + + err = keep_resources(efw, &efw->rx_stream, rate, mode); + if (err < 0) + return err; } return 0; From 5ad840728ac3f56008da03481a96d3ed175e7c3f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:13 +0900 Subject: [PATCH 343/626] ALSA: fireworks: don't set XRUN in stop streaming When stopping packet streaming, no need to stop PCM substream with XRUN state. This commit suppresses it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_stream.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 1abc15760513..61342c49dc38 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -43,7 +43,6 @@ end: static void stop_stream(struct snd_efw *efw, struct amdtp_stream *stream) { - amdtp_stream_pcm_abort(stream); amdtp_stream_stop(stream); if (stream == &efw->tx_stream) From da2af86d51ac32067c77759e40a162d684690a43 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:14 +0900 Subject: [PATCH 344/626] ALSA: oxfw: code refactoring for stop condition of packet streaming This commit unifies stop condition due to queueing error and unmatched state of the target device. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-stream.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index f230a9e44c3c..34ff673e6ff8 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -288,10 +288,6 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, if (err < 0) goto end; - /* packet queueing error */ - if (amdtp_streaming_error(stream)) - stop_stream(oxfw, stream); - err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); if (err < 0) goto end; @@ -300,7 +296,8 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, if (pcm_channels == 0) pcm_channels = formation.pcm; - if ((formation.rate != rate) || (formation.pcm != pcm_channels)) { + if (formation.rate != rate || formation.pcm != pcm_channels || + amdtp_streaming_error(stream)) { if (opposite != NULL) { err = check_connection_used_by_others(oxfw, opposite); if (err < 0) From 521b2e11fad0b4d6b36727ecca624710b5f81fd1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:15 +0900 Subject: [PATCH 345/626] ALSA: oxfw: set packet parameter according to current configuration After a call of pcm.hw_params, the state of target device is expected for applications. This commit retrieves the state and start packet streaming. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-stream.c | 48 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 34ff673e6ff8..1691fdc1a575 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -112,51 +112,51 @@ static void stop_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) cmp_connection_break(&oxfw->in_conn); } -static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream, - unsigned int rate, unsigned int pcm_channels) +static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { u8 **formats; + enum avc_general_plug_dir dir; struct cmp_connection *conn; struct snd_oxfw_stream_formation formation; - unsigned int i, midi_ports; + int i; int err; if (stream == &oxfw->rx_stream) { + dir = AVC_GENERAL_PLUG_DIR_IN; formats = oxfw->rx_stream_formats; conn = &oxfw->in_conn; } else { + dir = AVC_GENERAL_PLUG_DIR_OUT; formats = oxfw->tx_stream_formats; conn = &oxfw->out_conn; } - /* Get stream format */ + err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); + if (err < 0) + return err; + for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { + struct snd_oxfw_stream_formation fmt; + if (formats[i] == NULL) break; - err = snd_oxfw_stream_parse_format(formats[i], &formation); + err = snd_oxfw_stream_parse_format(formats[i], &fmt); if (err < 0) - goto end; - if (rate != formation.rate) - continue; - if (pcm_channels == 0 || pcm_channels == formation.pcm) + return err; + if (fmt.rate == formation.rate && fmt.pcm == formation.pcm && + fmt.midi == formation.midi) break; } - if (i == SND_OXFW_STREAM_FORMAT_ENTRIES) { - err = -EINVAL; - goto end; - } + if (i == SND_OXFW_STREAM_FORMAT_ENTRIES) + return -EINVAL; - pcm_channels = formation.pcm; - midi_ports = formation.midi * 8; + // The stream should have one pcm channels at least. + if (formation.pcm == 0) + return -EINVAL; - /* The stream should have one pcm channels at least */ - if (pcm_channels == 0) { - err = -EINVAL; - goto end; - } - err = amdtp_am824_set_parameters(stream, rate, pcm_channels, midi_ports, - false); + err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, + formation.midi * 8, false); if (err < 0) goto end; @@ -316,7 +316,7 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, /* Start opposite stream if needed. */ if (opposite && !amdtp_stream_running(opposite) && (opposite_substreams > 0)) { - err = start_stream(oxfw, opposite, rate, 0); + err = start_stream(oxfw, opposite); if (err < 0) { dev_err(&oxfw->unit->device, "fail to restart stream: %d\n", err); @@ -327,7 +327,7 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, /* Start requested stream. */ if (!amdtp_stream_running(stream)) { - err = start_stream(oxfw, stream, rate, pcm_channels); + err = start_stream(oxfw, stream); if (err < 0) dev_err(&oxfw->unit->device, "fail to start stream: %d\n", err); From 20358d4460bd4aa833b1ad79b79763887d9b75e4 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:16 +0900 Subject: [PATCH 346/626] ALSA: oxfw: start duplex streams if supported It's inconvenient to handle two isochronous context separately each other. This commit unifies the counters to handle the two at the same time. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-stream.c | 102 ++++++++++++++---------------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 1691fdc1a575..bb4ba6c196ea 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -254,96 +254,92 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, struct amdtp_stream *stream, unsigned int rate, unsigned int pcm_channels) { - struct amdtp_stream *opposite; struct snd_oxfw_stream_formation formation; enum avc_general_plug_dir dir; - unsigned int substreams, opposite_substreams; int err = 0; - if (stream == &oxfw->tx_stream) { - substreams = oxfw->capture_substreams; - opposite = &oxfw->rx_stream; - opposite_substreams = oxfw->playback_substreams; - dir = AVC_GENERAL_PLUG_DIR_OUT; - } else { - substreams = oxfw->playback_substreams; - opposite_substreams = oxfw->capture_substreams; + if (oxfw->capture_substreams == 0 && oxfw->playback_substreams == 0) + return -EIO; - if (oxfw->has_output) - opposite = &oxfw->rx_stream; - else - opposite = NULL; - - dir = AVC_GENERAL_PLUG_DIR_IN; + // Considering JACK/FFADO streaming: + // TODO: This can be removed hwdep functionality becomes popular. + err = check_connection_used_by_others(oxfw, &oxfw->rx_stream); + if (err < 0) + return err; + if (oxfw->has_output) { + err = check_connection_used_by_others(oxfw, &oxfw->tx_stream); + if (err < 0) + return err; } - if (substreams == 0) - goto end; - - /* - * Considering JACK/FFADO streaming: - * TODO: This can be removed hwdep functionality becomes popular. - */ - err = check_connection_used_by_others(oxfw, stream); - if (err < 0) - goto end; + if (stream == &oxfw->tx_stream) + dir = AVC_GENERAL_PLUG_DIR_OUT; + else + dir = AVC_GENERAL_PLUG_DIR_IN; err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); if (err < 0) - goto end; + return err; if (rate == 0) rate = formation.rate; if (pcm_channels == 0) pcm_channels = formation.pcm; if (formation.rate != rate || formation.pcm != pcm_channels || - amdtp_streaming_error(stream)) { - if (opposite != NULL) { - err = check_connection_used_by_others(oxfw, opposite); - if (err < 0) - goto end; - stop_stream(oxfw, opposite); - } - stop_stream(oxfw, stream); + amdtp_streaming_error(&oxfw->rx_stream) || + amdtp_streaming_error(&oxfw->tx_stream)) { + stop_stream(oxfw, &oxfw->rx_stream); + if (oxfw->has_output) + stop_stream(oxfw, &oxfw->tx_stream); err = set_stream_format(oxfw, stream, rate, pcm_channels); if (err < 0) { dev_err(&oxfw->unit->device, "fail to set stream format: %d\n", err); - goto end; + return err; } + } - /* Start opposite stream if needed. */ - if (opposite && !amdtp_stream_running(opposite) && - (opposite_substreams > 0)) { - err = start_stream(oxfw, opposite); + if (!amdtp_stream_running(&oxfw->rx_stream)) { + err = start_stream(oxfw, &oxfw->rx_stream); + if (err < 0) { + dev_err(&oxfw->unit->device, + "fail to start rx stream: %d\n", err); + goto error; + } + } + + if (oxfw->has_output) { + if (!amdtp_stream_running(&oxfw->tx_stream)) { + err = start_stream(oxfw, &oxfw->tx_stream); if (err < 0) { dev_err(&oxfw->unit->device, - "fail to restart stream: %d\n", err); - goto end; + "fail to start tx stream: %d\n", err); + goto error; } } } - /* Start requested stream. */ - if (!amdtp_stream_running(stream)) { - err = start_stream(oxfw, stream); - if (err < 0) - dev_err(&oxfw->unit->device, - "fail to start stream: %d\n", err); + return 0; +error: + stop_stream(oxfw, &oxfw->rx_stream); + cmp_connection_break(&oxfw->in_conn); + if (oxfw->has_output) { + stop_stream(oxfw, &oxfw->tx_stream); + cmp_connection_break(&oxfw->out_conn); } -end: return err; } void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { - if (((stream == &oxfw->tx_stream) && (oxfw->capture_substreams > 0)) || - ((stream == &oxfw->rx_stream) && (oxfw->playback_substreams > 0))) - return; + if (oxfw->capture_substreams == 0 && oxfw->playback_substreams == 0) { + stop_stream(oxfw, &oxfw->rx_stream); - stop_stream(oxfw, stream); + if (oxfw->has_output) + stop_stream(oxfw, &oxfw->tx_stream); + } } /* From 7efa19ab4848305a17aea542b09930e3d7d1bede Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:17 +0900 Subject: [PATCH 347/626] ALSA: oxfw: break packet streaming at bus-reset handler In most cases, recovery from bus reset is not successful. This commit aborts packet streaming in bus reset handler. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-stream.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index bb4ba6c196ea..806a7fded99d 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -363,17 +363,10 @@ void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { - struct cmp_connection *conn; + stop_stream(oxfw, &oxfw->rx_stream); - if (stream == &oxfw->tx_stream) - conn = &oxfw->out_conn; - else - conn = &oxfw->in_conn; - - if (cmp_connection_update(conn) < 0) - stop_stream(oxfw, stream); - else - amdtp_stream_update(stream); + if (oxfw->has_output) + stop_stream(oxfw, &oxfw->tx_stream); } int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw, From e34244dd2266773f699977c831b60a44fc3a164b Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:18 +0900 Subject: [PATCH 348/626] ALSA: oxfw: expand stop procedure for packet streaming The helper function stop packet streaming is not enough useful. This commit obsoletes it and expands its code. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-stream.c | 68 ++++++++++++++++--------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 806a7fded99d..561ceb09d927 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -101,17 +101,6 @@ static int set_stream_format(struct snd_oxfw *oxfw, struct amdtp_stream *s, return 0; } -static void stop_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) -{ - amdtp_stream_pcm_abort(stream); - amdtp_stream_stop(stream); - - if (stream == &oxfw->tx_stream) - cmp_connection_break(&oxfw->out_conn); - else - cmp_connection_break(&oxfw->in_conn); -} - static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { u8 **formats; @@ -158,28 +147,27 @@ static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, formation.midi * 8, false); if (err < 0) - goto end; + return err; err = cmp_connection_establish(conn, amdtp_stream_get_max_payload(stream)); if (err < 0) - goto end; + return err; - err = amdtp_stream_start(stream, - conn->resources.channel, - conn->speed); + err = amdtp_stream_start(stream, conn->resources.channel, conn->speed); if (err < 0) { cmp_connection_break(conn); - goto end; + return err; } - /* Wait first packet */ + // Wait first packet. if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { - stop_stream(oxfw, stream); - err = -ETIMEDOUT; + amdtp_stream_stop(stream); + cmp_connection_break(conn); + return -ETIMEDOUT; } -end: - return err; + + return 0; } static int check_connection_used_by_others(struct snd_oxfw *oxfw, @@ -288,9 +276,13 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, if (formation.rate != rate || formation.pcm != pcm_channels || amdtp_streaming_error(&oxfw->rx_stream) || amdtp_streaming_error(&oxfw->tx_stream)) { - stop_stream(oxfw, &oxfw->rx_stream); - if (oxfw->has_output) - stop_stream(oxfw, &oxfw->tx_stream); + amdtp_stream_stop(&oxfw->rx_stream); + cmp_connection_break(&oxfw->in_conn); + + if (oxfw->has_output) { + amdtp_stream_stop(&oxfw->tx_stream); + cmp_connection_break(&oxfw->out_conn); + } err = set_stream_format(oxfw, stream, rate, pcm_channels); if (err < 0) { @@ -322,10 +314,10 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, return 0; error: - stop_stream(oxfw, &oxfw->rx_stream); + amdtp_stream_stop(&oxfw->rx_stream); cmp_connection_break(&oxfw->in_conn); if (oxfw->has_output) { - stop_stream(oxfw, &oxfw->tx_stream); + amdtp_stream_stop(&oxfw->tx_stream); cmp_connection_break(&oxfw->out_conn); } return err; @@ -335,10 +327,13 @@ void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { if (oxfw->capture_substreams == 0 && oxfw->playback_substreams == 0) { - stop_stream(oxfw, &oxfw->rx_stream); + amdtp_stream_stop(&oxfw->rx_stream); + cmp_connection_break(&oxfw->in_conn); - if (oxfw->has_output) - stop_stream(oxfw, &oxfw->tx_stream); + if (oxfw->has_output) { + amdtp_stream_stop(&oxfw->tx_stream); + cmp_connection_break(&oxfw->out_conn); + } } } @@ -363,10 +358,17 @@ void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { - stop_stream(oxfw, &oxfw->rx_stream); + amdtp_stream_stop(&oxfw->rx_stream); + cmp_connection_break(&oxfw->in_conn); - if (oxfw->has_output) - stop_stream(oxfw, &oxfw->tx_stream); + amdtp_stream_pcm_abort(&oxfw->rx_stream); + + if (oxfw->has_output) { + amdtp_stream_stop(&oxfw->tx_stream); + cmp_connection_break(&oxfw->out_conn); + + amdtp_stream_pcm_abort(&oxfw->tx_stream); + } } int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw, From 779f0dba0b99f32276315ba40e812648b6ceed34 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:19 +0900 Subject: [PATCH 349/626] ALSA: oxfw: rename helper functions for duplex streams In former commits, ALSA oxfw driver handles two isochronous contexts at the same time, except for some devices which supports one endpoint of isochronous packet stream. This commit renames some helper functions so that they handles duplex streams. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-midi.c | 8 ++--- sound/firewire/oxfw/oxfw-pcm.c | 12 +++---- sound/firewire/oxfw/oxfw-stream.c | 60 ++++++++++++++++++++----------- sound/firewire/oxfw/oxfw.c | 17 ++------- sound/firewire/oxfw/oxfw.h | 14 +++----- 5 files changed, 58 insertions(+), 53 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-midi.c b/sound/firewire/oxfw/oxfw-midi.c index b7bbd77dfff1..31352cebdfe9 100644 --- a/sound/firewire/oxfw/oxfw-midi.c +++ b/sound/firewire/oxfw/oxfw-midi.c @@ -20,7 +20,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); oxfw->capture_substreams++; - err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->tx_stream, 0, 0); + err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->tx_stream, 0, 0); mutex_unlock(&oxfw->mutex); @@ -42,7 +42,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); oxfw->playback_substreams++; - err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->rx_stream, 0, 0); + err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->rx_stream, 0, 0); mutex_unlock(&oxfw->mutex); @@ -59,7 +59,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); oxfw->capture_substreams--; - snd_oxfw_stream_stop_simplex(oxfw, &oxfw->tx_stream); + snd_oxfw_stream_stop_duplex(oxfw); mutex_unlock(&oxfw->mutex); @@ -74,7 +74,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); oxfw->playback_substreams--; - snd_oxfw_stream_stop_simplex(oxfw, &oxfw->rx_stream); + snd_oxfw_stream_stop_duplex(oxfw); mutex_unlock(&oxfw->mutex); diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index b3f6503dd34d..253d79607bdf 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -255,7 +255,7 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) oxfw->capture_substreams--; - snd_oxfw_stream_stop_simplex(oxfw, &oxfw->tx_stream); + snd_oxfw_stream_stop_duplex(oxfw); mutex_unlock(&oxfw->mutex); @@ -270,7 +270,7 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) oxfw->playback_substreams--; - snd_oxfw_stream_stop_simplex(oxfw, &oxfw->rx_stream); + snd_oxfw_stream_stop_duplex(oxfw); mutex_unlock(&oxfw->mutex); @@ -284,8 +284,8 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) int err; mutex_lock(&oxfw->mutex); - err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->tx_stream, - runtime->rate, runtime->channels); + err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->tx_stream, + runtime->rate, runtime->channels); mutex_unlock(&oxfw->mutex); if (err < 0) goto end; @@ -301,8 +301,8 @@ static int pcm_playback_prepare(struct snd_pcm_substream *substream) int err; mutex_lock(&oxfw->mutex); - err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->rx_stream, - runtime->rate, runtime->channels); + err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->rx_stream, + runtime->rate, runtime->channels); mutex_unlock(&oxfw->mutex); if (err < 0) goto end; diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 561ceb09d927..52cf815c27f7 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -194,8 +194,7 @@ static int check_connection_used_by_others(struct snd_oxfw *oxfw, return err; } -int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream) +static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { struct cmp_connection *conn; enum cmp_direction c_dir; @@ -214,13 +213,12 @@ int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw, err = cmp_connection_init(conn, oxfw->unit, c_dir, 0); if (err < 0) - goto end; + return err; err = amdtp_am824_init(stream, oxfw->unit, s_dir, CIP_NONBLOCKING); if (err < 0) { - amdtp_stream_destroy(stream); cmp_connection_destroy(conn); - goto end; + return err; } /* @@ -234,13 +232,13 @@ int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw, if (oxfw->wrong_dbs) oxfw->tx_stream.flags |= CIP_WRONG_DBS; } -end: - return err; + + return 0; } -int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream, - unsigned int rate, unsigned int pcm_channels) +int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw, + struct amdtp_stream *stream, + unsigned int rate, unsigned int pcm_channels) { struct snd_oxfw_stream_formation formation; enum avc_general_plug_dir dir; @@ -323,8 +321,7 @@ error: return err; } -void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream) +void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw) { if (oxfw->capture_substreams == 0 && oxfw->playback_substreams == 0) { amdtp_stream_stop(&oxfw->rx_stream); @@ -337,12 +334,7 @@ void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw, } } -/* - * This function should be called before starting the stream or after stopping - * the streams. - */ -void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream) +static void destroy_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { struct cmp_connection *conn; @@ -355,8 +347,36 @@ void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, cmp_connection_destroy(conn); } -void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream) +int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw) +{ + int err; + + err = init_stream(oxfw, &oxfw->rx_stream); + if (err < 0) + return err; + + if (oxfw->has_output) { + err = init_stream(oxfw, &oxfw->tx_stream); + if (err < 0) { + destroy_stream(oxfw, &oxfw->rx_stream); + return err; + } + } + + return 0; +} + +// This function should be called before starting the stream or after stopping +// the streams. +void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw) +{ + destroy_stream(oxfw, &oxfw->rx_stream); + + if (oxfw->has_output) + destroy_stream(oxfw, &oxfw->tx_stream); +} + +void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw) { amdtp_stream_stop(&oxfw->rx_stream); cmp_connection_break(&oxfw->in_conn); diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 3d27f3378d5d..2de26a9987f8 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -118,9 +118,7 @@ static void oxfw_card_free(struct snd_card *card) { struct snd_oxfw *oxfw = card->private_data; - snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); - if (oxfw->has_output) - snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); + snd_oxfw_stream_destroy_duplex(oxfw); } static int detect_quirks(struct snd_oxfw *oxfw) @@ -211,14 +209,9 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->rx_stream); + err = snd_oxfw_stream_init_duplex(oxfw); if (err < 0) goto error; - if (oxfw->has_output) { - err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->tx_stream); - if (err < 0) - goto error; - } err = snd_oxfw_create_pcm(oxfw); if (err < 0) @@ -285,11 +278,7 @@ static void oxfw_bus_reset(struct fw_unit *unit) if (oxfw->registered) { mutex_lock(&oxfw->mutex); - - snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream); - if (oxfw->has_output) - snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream); - + snd_oxfw_stream_update_duplex(oxfw); mutex_unlock(&oxfw->mutex); if (oxfw->entry->vendor_id == OUI_STANTON) diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index d54d4a9ac4a1..911a452f94db 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -99,17 +99,13 @@ int avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate, enum avc_general_plug_dir dir, unsigned short pid); -int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream); -int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, +int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw); +int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw, struct amdtp_stream *stream, unsigned int rate, unsigned int pcm_channels); -void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream); -void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream); -void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream); +void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw); +void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw); +void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw); struct snd_oxfw_stream_formation { unsigned int rate; From 4a0a04729a44ea317270885e1722636b156cf620 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:20 +0900 Subject: [PATCH 350/626] ALSA: oxfw: unify substreams counter In former commits, two isochronous contexts are handles at the same time. This commit unifies stream counters to obsolete them. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-midi.c | 8 ++++---- sound/firewire/oxfw/oxfw-pcm.c | 8 ++++---- sound/firewire/oxfw/oxfw-stream.c | 4 ++-- sound/firewire/oxfw/oxfw.h | 3 +-- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-midi.c b/sound/firewire/oxfw/oxfw-midi.c index 31352cebdfe9..092493497f1a 100644 --- a/sound/firewire/oxfw/oxfw-midi.c +++ b/sound/firewire/oxfw/oxfw-midi.c @@ -19,7 +19,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); - oxfw->capture_substreams++; + ++oxfw->substreams_count; err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->tx_stream, 0, 0); mutex_unlock(&oxfw->mutex); @@ -41,7 +41,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); - oxfw->playback_substreams++; + ++oxfw->substreams_count; err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->rx_stream, 0, 0); mutex_unlock(&oxfw->mutex); @@ -58,7 +58,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); - oxfw->capture_substreams--; + --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); mutex_unlock(&oxfw->mutex); @@ -73,7 +73,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); - oxfw->playback_substreams--; + --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); mutex_unlock(&oxfw->mutex); diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 253d79607bdf..79c8e514bed9 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -220,7 +220,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&oxfw->mutex); - oxfw->capture_substreams++; + ++oxfw->substreams_count; mutex_unlock(&oxfw->mutex); } @@ -239,7 +239,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&oxfw->mutex); - oxfw->playback_substreams++; + ++oxfw->substreams_count; mutex_unlock(&oxfw->mutex); } @@ -253,7 +253,7 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&oxfw->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - oxfw->capture_substreams--; + --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); @@ -268,7 +268,7 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&oxfw->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - oxfw->playback_substreams--; + --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 52cf815c27f7..ebfe0777773b 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -244,7 +244,7 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir; int err = 0; - if (oxfw->capture_substreams == 0 && oxfw->playback_substreams == 0) + if (oxfw->substreams_count == 0) return -EIO; // Considering JACK/FFADO streaming: @@ -323,7 +323,7 @@ error: void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw) { - if (oxfw->capture_substreams == 0 && oxfw->playback_substreams == 0) { + if (oxfw->substreams_count == 0) { amdtp_stream_stop(&oxfw->rx_stream); cmp_connection_break(&oxfw->in_conn); diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index 911a452f94db..e0c825288a24 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -52,8 +52,7 @@ struct snd_oxfw { struct cmp_connection in_conn; struct amdtp_stream tx_stream; struct amdtp_stream rx_stream; - unsigned int capture_substreams; - unsigned int playback_substreams; + unsigned int substreams_count; unsigned int midi_input_ports; unsigned int midi_output_ports; From 4f380d0070528da8b93c4ac3994c20097393f6dd Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:21 +0900 Subject: [PATCH 351/626] ALSA: oxfw: configure packet format in pcm.hw_params callback This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. At present, several operations are done in pcm.prepare callback. To reduce load of the callback, This commit splits out an operation to set packet format in pcm.hw_params callback. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-midi.c | 14 +++++++--- sound/firewire/oxfw/oxfw-pcm.c | 26 +++++++++++------- sound/firewire/oxfw/oxfw-stream.c | 44 ++++++++++++++++++++++--------- sound/firewire/oxfw/oxfw.h | 7 ++--- 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-midi.c b/sound/firewire/oxfw/oxfw-midi.c index 092493497f1a..9ba62778add2 100644 --- a/sound/firewire/oxfw/oxfw-midi.c +++ b/sound/firewire/oxfw/oxfw-midi.c @@ -19,8 +19,11 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); - ++oxfw->substreams_count; - err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->tx_stream, 0, 0); + err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0); + if (err >= 0) { + ++oxfw->substreams_count; + err = snd_oxfw_stream_start_duplex(oxfw); + } mutex_unlock(&oxfw->mutex); @@ -41,8 +44,11 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) mutex_lock(&oxfw->mutex); - ++oxfw->substreams_count; - err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->rx_stream, 0, 0); + err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0); + if (err >= 0) { + ++oxfw->substreams_count; + err = snd_oxfw_stream_start_duplex(oxfw); + } mutex_unlock(&oxfw->mutex); diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 79c8e514bed9..b08b850d53ea 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -219,12 +219,18 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + unsigned int channels = params_channels(hw_params); + mutex_lock(&oxfw->mutex); - ++oxfw->substreams_count; + err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, + rate, channels); + if (err >= 0) + ++oxfw->substreams_count; mutex_unlock(&oxfw->mutex); } - return 0; + return err; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) @@ -238,8 +244,14 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + unsigned int channels = params_channels(hw_params); + mutex_lock(&oxfw->mutex); - ++oxfw->substreams_count; + err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, + rate, channels); + if (err >= 0) + ++oxfw->substreams_count; mutex_unlock(&oxfw->mutex); } @@ -280,12 +292,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) static int pcm_capture_prepare(struct snd_pcm_substream *substream) { struct snd_oxfw *oxfw = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; mutex_lock(&oxfw->mutex); - err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->tx_stream, - runtime->rate, runtime->channels); + err = snd_oxfw_stream_start_duplex(oxfw); mutex_unlock(&oxfw->mutex); if (err < 0) goto end; @@ -297,12 +307,10 @@ end: static int pcm_playback_prepare(struct snd_pcm_substream *substream) { struct snd_oxfw *oxfw = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; mutex_lock(&oxfw->mutex); - err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->rx_stream, - runtime->rate, runtime->channels); + err = snd_oxfw_stream_start_duplex(oxfw); mutex_unlock(&oxfw->mutex); if (err < 0) goto end; diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index ebfe0777773b..373154d8ee0e 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -236,16 +236,13 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) return 0; } -int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream, - unsigned int rate, unsigned int pcm_channels) +int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, + struct amdtp_stream *stream, + unsigned int rate, unsigned int pcm_channels) { struct snd_oxfw_stream_formation formation; enum avc_general_plug_dir dir; - int err = 0; - - if (oxfw->substreams_count == 0) - return -EIO; + int err; // Considering JACK/FFADO streaming: // TODO: This can be removed hwdep functionality becomes popular. @@ -266,14 +263,11 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw, err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); if (err < 0) return err; - if (rate == 0) + if (rate == 0) { rate = formation.rate; - if (pcm_channels == 0) pcm_channels = formation.pcm; - - if (formation.rate != rate || formation.pcm != pcm_channels || - amdtp_streaming_error(&oxfw->rx_stream) || - amdtp_streaming_error(&oxfw->tx_stream)) { + } + if (formation.rate != rate || formation.pcm != pcm_channels) { amdtp_stream_stop(&oxfw->rx_stream); cmp_connection_break(&oxfw->in_conn); @@ -281,7 +275,10 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw, amdtp_stream_stop(&oxfw->tx_stream); cmp_connection_break(&oxfw->out_conn); } + } + if (oxfw->substreams_count == 0 || + formation.rate != rate || formation.pcm != pcm_channels) { err = set_stream_format(oxfw, stream, rate, pcm_channels); if (err < 0) { dev_err(&oxfw->unit->device, @@ -290,6 +287,27 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw, } } + return 0; +} + +int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw) +{ + int err; + + if (oxfw->substreams_count == 0) + return -EIO; + + if (amdtp_streaming_error(&oxfw->rx_stream) || + amdtp_streaming_error(&oxfw->tx_stream)) { + amdtp_stream_stop(&oxfw->rx_stream); + cmp_connection_break(&oxfw->in_conn); + + if (oxfw->has_output) { + amdtp_stream_stop(&oxfw->tx_stream); + cmp_connection_break(&oxfw->out_conn); + } + } + if (!amdtp_stream_running(&oxfw->rx_stream)) { err = start_stream(oxfw, &oxfw->rx_stream); if (err < 0) { diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index e0c825288a24..d4d4926c28cf 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -99,9 +99,10 @@ int avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate, unsigned short pid); int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw); -int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw, - struct amdtp_stream *stream, - unsigned int rate, unsigned int pcm_channels); +int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, + struct amdtp_stream *stream, + unsigned int rate, unsigned int pcm_channels); +int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw); void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw); void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw); void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw); From 0356ce3adda0a7b5ef49d580790e94b9c80e8862 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 12 Jun 2019 17:44:22 +0900 Subject: [PATCH 352/626] ALSA: oxfw: configure stream parameter in pcm.hw_params callback This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. This commit splits out an operation to configure stream parameters into pcm.hw_params callback. In pcm.prepare callback, establishing connections and start isochronous contexts. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-stream.c | 97 ++++++++++++++++++------------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 373154d8ee0e..837733f10736 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -103,51 +103,13 @@ static int set_stream_format(struct snd_oxfw *oxfw, struct amdtp_stream *s, static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) { - u8 **formats; - enum avc_general_plug_dir dir; struct cmp_connection *conn; - struct snd_oxfw_stream_formation formation; - int i; int err; - if (stream == &oxfw->rx_stream) { - dir = AVC_GENERAL_PLUG_DIR_IN; - formats = oxfw->rx_stream_formats; + if (stream == &oxfw->rx_stream) conn = &oxfw->in_conn; - } else { - dir = AVC_GENERAL_PLUG_DIR_OUT; - formats = oxfw->tx_stream_formats; + else conn = &oxfw->out_conn; - } - - err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); - if (err < 0) - return err; - - for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { - struct snd_oxfw_stream_formation fmt; - - if (formats[i] == NULL) - break; - - err = snd_oxfw_stream_parse_format(formats[i], &fmt); - if (err < 0) - return err; - if (fmt.rate == formation.rate && fmt.pcm == formation.pcm && - fmt.midi == formation.midi) - break; - } - if (i == SND_OXFW_STREAM_FORMAT_ENTRIES) - return -EINVAL; - - // The stream should have one pcm channels at least. - if (formation.pcm == 0) - return -EINVAL; - - err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, - formation.midi * 8, false); - if (err < 0) - return err; err = cmp_connection_establish(conn, amdtp_stream_get_max_payload(stream)); @@ -236,6 +198,51 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) return 0; } +static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream) +{ + enum avc_general_plug_dir dir; + u8 **formats; + struct snd_oxfw_stream_formation formation; + int i; + int err; + + if (stream == &oxfw->rx_stream) { + dir = AVC_GENERAL_PLUG_DIR_IN; + formats = oxfw->rx_stream_formats; + } else { + dir = AVC_GENERAL_PLUG_DIR_OUT; + formats = oxfw->tx_stream_formats; + } + + err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); + if (err < 0) + return err; + + for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { + struct snd_oxfw_stream_formation fmt; + + if (formats[i] == NULL) + break; + + err = snd_oxfw_stream_parse_format(formats[i], &fmt); + if (err < 0) + return err; + + if (fmt.rate == formation.rate && fmt.pcm == formation.pcm && + fmt.midi == formation.midi) + break; + } + if (i == SND_OXFW_STREAM_FORMAT_ENTRIES) + return -EINVAL; + + // The stream should have one pcm channels at least. + if (formation.pcm == 0) + return -EINVAL; + + return amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, + formation.midi * 8, false); +} + int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, struct amdtp_stream *stream, unsigned int rate, unsigned int pcm_channels) @@ -285,6 +292,16 @@ int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, "fail to set stream format: %d\n", err); return err; } + + err = keep_resources(oxfw, &oxfw->rx_stream); + if (err < 0) + return err; + + if (oxfw->has_output) { + err = keep_resources(oxfw, &oxfw->tx_stream); + if (err < 0) + return err; + } } return 0; From c72d3a0a93471b95084339e5cba927d516724b83 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 13 Jun 2019 12:35:22 +0900 Subject: [PATCH 353/626] ALSA: dice: fix compiler warning due to returning uninitialized value This commit fixes the warning due to returning uninitialized value from start_streams() helper function. sound/firewire/dice/dice-stream.c: In function 'start_streams.isra.0': >> sound/firewire/dice/dice-stream.c:350:6: warning: 'err' may be used uninitialized in this function [-Wmaybe-uninitialized] int err; ^~~ Reported-by: kbuild test robot Fixes: 3cd2c2d780a2 ("ALSA: dice: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index f61b99a72655..e9e5c5fffb70 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -389,7 +389,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, return err; } - return err; + return 0; } /* From f94287b653542e09e7004bae5f0d9d37fcaa89c8 Mon Sep 17 00:00:00 2001 From: "Lai, Poey Seng" Date: Fri, 14 Jun 2019 00:21:39 +0800 Subject: [PATCH 354/626] ALSA: hda: Add Elkhart Lake PCI ID Add HD Audio Device PCI ID for the Intel Elkhart Lake platform. Signed-off-by: Lai, Poey Seng Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c0b466c96340..922c9b930124 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2388,6 +2388,9 @@ static const struct pci_device_id azx_ids[] = { /* Icelake */ { PCI_DEVICE(0x8086, 0x34c8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Elkhart Lake */ + { PCI_DEVICE(0x8086, 0x4b55), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Broxton-P(Apollolake) */ { PCI_DEVICE(0x8086, 0x5a98), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, From 3e985effb25edcf500a58f41be71cc049b1b837f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 12 Jun 2019 11:36:54 -0500 Subject: [PATCH 355/626] ALSA: hda: remove an unused field from struct hda_codec The .jacks field in struct hda_codec is unused and seems to be a duplicate of .jacktbl, remove it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hda_codec.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index cc7c8d42d4fd..2a1d1ad44d66 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -281,9 +281,6 @@ struct hda_codec { unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */ struct delayed_work jackpoll_work; - /* jack detection */ - struct snd_array jacks; - int depop_delay; /* depop delay in ms, -1 for default delay time */ /* fix-up list */ From 855b5e01c0732d66c306cdd5215c3337e5311899 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 13 Jun 2019 15:09:01 +0200 Subject: [PATCH 356/626] ALSA: hda/hdmi - consider eld_valid also in sync_eld_via_acomp() In the commit 7f641e26a6df9269cb25dd7a4b0a91d6586ed441 (ALSA: hda/hdmi - Consider eld_valid when reporting jack event) the eld_valid check was added for the jack event reports. Do the same in sync_eld_via_acomp() function. Apparently, it is required for the NVIDIA proprietary driver (monitor presence reported first, but ELD is available later). Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 0c61c05503f5..b522314ec5be 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1627,7 +1627,8 @@ static void sync_eld_via_acomp(struct hda_codec *codec, if (jack == NULL) goto unlock; snd_jack_report(jack, - eld->monitor_present ? SND_JACK_AVOUT : 0); + (eld->monitor_present && eld->eld_valid) ? + SND_JACK_AVOUT : 0); unlock: mutex_unlock(&per_pin->lock); } From cbb9f8ccc8232b4647c4180af653eee744818221 Mon Sep 17 00:00:00 2001 From: John Hsu Date: Mon, 10 Jun 2019 11:40:40 +0800 Subject: [PATCH 357/626] ASoC: nau8825: fix fake interruption when booting There is no pull-up resistor at IRQ line where it connects from the codec to SoC. When booting, the signal of IRQ pin will keep low which makes the SoC invoke the ISR repeatedly because the IRQ is registered trigger low. It will not stop until the codec sets up the interruption and pulls the signal high. In the patch, nau8825 will internally pull the signal to high at booting in case the fake interrupts happen. Signed-off-by: John Hsu Tested-by: Cheng-Yi Chiang Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 4 ++++ sound/soc/codecs/nau8825.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 47e65cf99879..83ec841f7865 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -1881,6 +1881,10 @@ static void nau8825_init_regs(struct nau8825 *nau8825) NAU8825_JACK_EJECT_DEBOUNCE_MASK, nau8825->jack_eject_debounce << NAU8825_JACK_EJECT_DEBOUNCE_SFT); + /* Pull up IRQ pin */ + regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, + NAU8825_IRQ_PIN_PULLUP | NAU8825_IRQ_PIN_PULL_EN, + NAU8825_IRQ_PIN_PULLUP | NAU8825_IRQ_PIN_PULL_EN); /* Mask unneeded IRQs: 1 - disable, 0 - enable */ regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, 0x7ff, 0x7ff); diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index f6074c618569..3f41897ed3f6 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h @@ -171,6 +171,8 @@ #define NAU8825_JACK_POLARITY (1 << 1) /* 0 - active low, 1 - active high */ /* INTERRUPT_MASK (0xf) */ +#define NAU8825_IRQ_PIN_PULLUP (1 << 14) +#define NAU8825_IRQ_PIN_PULL_EN (1 << 13) #define NAU8825_IRQ_OUTPUT_EN (1 << 11) #define NAU8825_IRQ_HEADSET_COMPLETE_EN (1 << 10) #define NAU8825_IRQ_RMS_EN (1 << 8) From fc30f2adb621aa6d6c59f0276d06004dcb204a56 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 12 Jun 2019 11:39:58 -0500 Subject: [PATCH 358/626] ASoC: Intel: bxt-da7219-max98357a: add BE dailink for dmic16k We need dmic16k BE(and FE, in tplg file) dailink for keyword detection feature on bxt-da7219-max98357a machine, here add it in driver side. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/bxt_da7219_max98357a.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index d712623854a3..0f7610c5fd53 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -412,6 +412,10 @@ SND_SOC_DAILINK_DEF(ssp1_codec, SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); + +SND_SOC_DAILINK_DEF(dmic16k_pin, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); + SND_SOC_DAILINK_DEF(dmic_codec, DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); @@ -586,6 +590,14 @@ static struct snd_soc_dai_link broxton_dais[] = { .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, + { + .name = "dmic16k", + .id = 6, + .be_hw_params_fixup = broxton_dmic_fixup, + .dpcm_capture = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), + }, }; #define NAME_SIZE 32 From 9aa892d2c1a0aa4f4287aa1d922602ca0e9db990 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 13 Jun 2019 18:04:23 +0200 Subject: [PATCH 359/626] ALSA: pci: echoaudio: remove variable which is a constant Checking a variable which is always '1' has no use. Signed-off-by: Wolfram Sang Signed-off-by: Takashi Iwai --- sound/pci/echoaudio/echoaudio_dsp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index b181752b8481..50d4a87a6bb3 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c @@ -1058,7 +1058,6 @@ static int allocate_pipes(struct echoaudio *chip, struct audiopipe *pipe, { int i; u32 channel_mask; - char is_cyclic; dev_dbg(chip->card->dev, "allocate_pipes: ch=%d int=%d\n", pipe_index, interleave); @@ -1066,8 +1065,6 @@ static int allocate_pipes(struct echoaudio *chip, struct audiopipe *pipe, if (chip->bad_board) return -EIO; - is_cyclic = 1; /* This driver uses cyclic buffers only */ - for (channel_mask = i = 0; i < interleave; i++) channel_mask |= 1 << (pipe_index + i); if (chip->pipe_alloc_mask & channel_mask) { @@ -1078,8 +1075,8 @@ static int allocate_pipes(struct echoaudio *chip, struct audiopipe *pipe, chip->comm_page->position[pipe_index] = 0; chip->pipe_alloc_mask |= channel_mask; - if (is_cyclic) - chip->pipe_cyclic_mask |= channel_mask; + /* This driver uses cyclic buffers only */ + chip->pipe_cyclic_mask |= channel_mask; pipe->index = pipe_index; pipe->interleave = interleave; pipe->state = PIPE_STATE_STOPPED; From 47c317b786b6c1efc2cb3cdb894fd323422fe5ea Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Jun 2019 13:42:30 +0200 Subject: [PATCH 360/626] ASoC: meson: axg-tdmin: right_j is not supported Right justified format is actually not supported by the amlogic tdm input decoder. Fixes: 13a22e6a98f8 ("ASoC: meson: add tdm input driver") Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdmin.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c index a790f925a4ef..cb87f17f3e95 100644 --- a/sound/soc/meson/axg-tdmin.c +++ b/sound/soc/meson/axg-tdmin.c @@ -121,7 +121,6 @@ static int axg_tdmin_prepare(struct regmap *map, break; case SND_SOC_DAIFMT_LEFT_J: - case SND_SOC_DAIFMT_RIGHT_J: case SND_SOC_DAIFMT_DSP_B: break; From 7e0d7d0fbd06af0507611f85dba8daf24832abd9 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Jun 2019 13:42:31 +0200 Subject: [PATCH 361/626] ASoC: meson: axg-tdmout: right_j is not supported Right justified format is actually not supported by the amlogic tdm output encoder. Fixes: c41c2a355b86 ("ASoC: meson: add tdm output driver") Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdmout.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/meson/axg-tdmout.c b/sound/soc/meson/axg-tdmout.c index 527bfc4487e0..86537fc0ecb5 100644 --- a/sound/soc/meson/axg-tdmout.c +++ b/sound/soc/meson/axg-tdmout.c @@ -137,7 +137,6 @@ static int axg_tdmout_prepare(struct regmap *map, break; case SND_SOC_DAIFMT_LEFT_J: - case SND_SOC_DAIFMT_RIGHT_J: case SND_SOC_DAIFMT_DSP_B: skew += 1; break; From cb36ff785e868992e96e8b9e5a0c2822b680a9e2 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Jun 2019 13:42:32 +0200 Subject: [PATCH 362/626] ASoC: meson: axg-tdm: fix sample clock inversion The content of SND_SOC_DAIFMT_FORMAT_MASK is a number, not a bitfield, so the test to check if the format is i2s is wrong. Because of this the clock setting may be wrong. For example, the sample clock gets inverted in DSP B mode, when it should not. Fix the lrclk invert helper function Fixes: 1a11d88f499c ("ASoC: meson: add tdm formatter base driver") Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/meson/axg-tdm.h b/sound/soc/meson/axg-tdm.h index e578b6f40a07..5774ce0916d4 100644 --- a/sound/soc/meson/axg-tdm.h +++ b/sound/soc/meson/axg-tdm.h @@ -40,7 +40,7 @@ struct axg_tdm_iface { static inline bool axg_tdm_lrclk_invert(unsigned int fmt) { - return (fmt & SND_SOC_DAIFMT_I2S) ^ + return ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) ^ !!(fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_NB_IF)); } From 489f231e0f4c44d4d019aa5c26e1c3f147875f13 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 13 Jun 2019 14:54:12 +0300 Subject: [PATCH 363/626] ASoC: codec: hdac_hdmi: fix pin connections at cvt enable In display codecs supported by hdac_hdmi, the connection indices are shared by all converters. At boot and resume from suspend, the connection state may be reset to default values. In case of multiple connected pins (multiple monitors connected with audio capability), routing and mute status of pins that are not connected to any PCM, may interfere with other pins. E.g. after resume from S3 with multiple monitors, unless all converters are in active use, playback to some PCMs may be muted due to the default settings of unrelated converters. Avoid this by ensuring all pin:cvt selections are correct in codec whenever a converter is enabled for playback. Signed-off-by: Kai Vehmanen Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 660e0587f399..7eba57157bb9 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -546,6 +546,29 @@ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt( return NULL; } +/* + * Go through all converters and ensure connection is set to + * the correct pin as set via kcontrols. + */ +static void hdac_hdmi_verify_connect_sel_all_pins(struct hdac_device *hdev) +{ + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); + struct hdac_hdmi_port *port; + struct hdac_hdmi_cvt *cvt; + int cvt_idx = 0; + + list_for_each_entry(cvt, &hdmi->cvt_list, head) { + port = hdac_hdmi_get_port_from_cvt(hdev, hdmi, cvt); + if (port && port->pin) { + snd_hdac_codec_write(hdev, port->pin->nid, 0, + AC_VERB_SET_CONNECT_SEL, cvt_idx); + dev_dbg(&hdev->dev, "%s: %s set connect %d -> %d\n", + __func__, cvt->name, port->pin->nid, cvt_idx); + } + ++cvt_idx; + } +} + /* * This tries to get a valid pin and set the HW constraints based on the * ELD. Even if a valid pin is not found return success so that device open @@ -806,6 +829,14 @@ static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w, AC_VERB_SET_CHANNEL_STREAMID, pcm->stream_tag); snd_hdac_codec_write(hdev, cvt->nid, 0, AC_VERB_SET_STREAM_FORMAT, pcm->format); + + /* + * The connection indices are shared by all converters and + * may interfere with each other. Ensure correct + * routing for all converters at stream start. + */ + hdac_hdmi_verify_connect_sel_all_pins(hdev); + break; case SND_SOC_DAPM_POST_PMD: From 05113483fd300d7a4605a726770e7255e29f1ac7 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Jun 2019 13:42:33 +0200 Subject: [PATCH 364/626] ASoC: meson: axg-tdm: consistently use SND_SOC_DAIFMT defines There a mix of SND_SOC_DAIFMT_ and SND_SOC_DAI_FORMAT_ in axg-tdm-interface.c. Even, if this is currently the same thing, lets use the same group consistently. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm-interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 585ce030b79b..d51f3344be7c 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -306,8 +306,8 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream, } break; - case SND_SOC_DAI_FORMAT_DSP_A: - case SND_SOC_DAI_FORMAT_DSP_B: + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: break; default: From 2f7e015c1f20cfdbe97df25868abbfa8b7514778 Mon Sep 17 00:00:00 2001 From: Nathan Huckleberry Date: Wed, 12 Jun 2019 16:25:02 -0700 Subject: [PATCH 365/626] ASoC: tas571x: Fix -Wunused-const-variable Clang produces the following warning sound/soc/codecs/tas571x.c:666:38: warning: unused variable 'tas5721_controls' [-Wunused-const-variable] In the chip struct definition tas5711_controls is used rather than tac5712_controls. Looks like a typo was made in the original commit. Since tac5711_controls is identical to tas5721_controls we can just swap them Cc: clang-built-linux@googlegroups.com Link: https://github.com/ClangBuiltLinux/linux/issues/522 Signed-off-by: Nathan Huckleberry Signed-off-by: Mark Brown --- sound/soc/codecs/tas571x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index ca2dfe12344e..684b7afa9252 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -725,8 +725,8 @@ static const struct regmap_config tas5721_regmap_config = { static const struct tas571x_chip tas5721_chip = { .supply_names = tas5721_supply_names, .num_supply_names = ARRAY_SIZE(tas5721_supply_names), - .controls = tas5711_controls, - .num_controls = ARRAY_SIZE(tas5711_controls), + .controls = tas5721_controls, + .num_controls = ARRAY_SIZE(tas5721_controls), .regmap_config = &tas5721_regmap_config, .vol_reg_size = 1, }; From 3e6de89409bf7ad149bfb05dd0dce6c5678ea0a8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 12 Jun 2019 11:38:45 -0500 Subject: [PATCH 366/626] ASoC: soc-topology: fix modern dai link style The topology code can create a FE DAI link but did not allocate the memory for a platform component - whose name can be overridden at a later time. Fixes: 23b946ce2808b ("ASoC: soc-topology: use modern dai_link style") Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index f485f7f751a1..b538412e4bcf 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1882,8 +1882,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, struct snd_soc_dai_link_component *dlc; int ret; - /* link + cpu + codec */ - link = kzalloc(sizeof(*link) + (2 * sizeof(*dlc)), GFP_KERNEL); + /* link + cpu + codec + platform */ + link = kzalloc(sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; @@ -1891,9 +1891,11 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->cpus = &dlc[0]; link->codecs = &dlc[1]; + link->platforms = &dlc[2]; link->num_cpus = 1; link->num_codecs = 1; + link->num_platforms = 1; if (strlen(pcm->pcm_name)) { link->name = kstrdup(pcm->pcm_name, GFP_KERNEL); @@ -1907,6 +1909,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->codecs->name = "snd-soc-dummy"; link->codecs->dai_name = "snd-soc-dummy-dai"; + link->platforms->name = "snd-soc-dummy"; + /* enable DPCM */ link->dynamic = 1; link->dpcm_playback = le32_to_cpu(pcm->playback); From 4cee883e97b6095e23f5d72543da93e1506ff8c2 Mon Sep 17 00:00:00 2001 From: Dragos Tarcatu Date: Wed, 12 Jun 2019 11:57:01 -0500 Subject: [PATCH 367/626] ASOC: SOF: ipc: prevent logging trace messages If the firmware is set for verbose tracing, the kernel log is flooded with ipc rx/ipc rx done messages. Prevent logging those unless the verbose IPC debugging config option is set. Signed-off-by: Dragos Tarcatu Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 558b596e2133..f3eb46bc808b 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -196,7 +196,8 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd) #else static inline void ipc_log_header(struct device *dev, u8 *text, u32 cmd) { - dev_dbg(dev, "%s: 0x%x\n", text, cmd); + if ((cmd & SOF_GLB_TYPE_MASK) != SOF_IPC_GLB_TRACE_MSG) + dev_dbg(dev, "%s: 0x%x\n", text, cmd); } #endif From b943f798011346589bd9ae994e5755e776756a31 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 12 Jun 2019 11:57:02 -0500 Subject: [PATCH 368/626] ASoC: SOF: uapi: align comments with firmware files No functional change, just mirror firmware comment changes Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 4 ++-- include/sound/sof/trace.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 4978999fd362..41dcabf89899 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -84,9 +84,9 @@ struct sof_ipc_buffer { struct sof_ipc_comp_config { struct sof_ipc_cmd_hdr hdr; uint32_t periods_sink; /**< 0 means variable */ - uint32_t periods_source; /**< 0 means variable */ + uint32_t periods_source;/**< 0 means variable */ uint32_t reserved1; /**< reserved */ - uint32_t frame_fmt; /**< SOF_IPC_FRAME_ */ + uint32_t frame_fmt; /**< SOF_IPC_FRAME_ */ uint32_t xrun_action; /* reserved for future use */ diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h index 2187ff7d07ce..9257d5473d97 100644 --- a/include/sound/sof/trace.h +++ b/include/sound/sof/trace.h @@ -66,7 +66,9 @@ struct sof_ipc_dma_trace_posn { #define SOF_IPC_PANIC_WFI (SOF_IPC_PANIC_MAGIC | 0xa) #define SOF_IPC_PANIC_ASSERT (SOF_IPC_PANIC_MAGIC | 0xb) -/* panic info include filename and line number */ +/* panic info include filename and line number + * filename array will not include null terminator if fully filled + */ struct sof_ipc_panic_info { struct sof_ipc_hdr hdr; uint32_t code; /* SOF_IPC_PANIC_ */ From f1fd9d0e6dbae9c7cdd7e82fe3055ec7b790abb6 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 12 Jun 2019 11:57:03 -0500 Subject: [PATCH 369/626] ASoC: SOF: intel: extend IPC dump information Extend the HDA IPC dump implementation with status of key IRQ registers. This is useful to debug IPC timeouts and similar issues. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 2 ++ sound/soc/sof/intel/hda.c | 29 +++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 2 ++ 3 files changed, 33 insertions(+) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 9a4927b6b6ae..d59305787fc3 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -168,6 +168,8 @@ static void cnl_ipc_dump(struct snd_sof_dev *sdev) u32 hipcida; u32 hipctdr; + hda_ipc_irq_dump(sdev); + /* read IPC status */ hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA); hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 47b508463218..af546e42e1d9 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -15,6 +15,9 @@ * Hardware interface for generic Intel audio DSP HDA IP */ +#include +#include + #include #include #include @@ -183,12 +186,38 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags) } } +void hda_ipc_irq_dump(struct snd_sof_dev *sdev) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + u32 adspis; + u32 intsts; + u32 intctl; + u32 ppsts; + u8 rirbsts; + + /* read key IRQ stats and config registers */ + adspis = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS); + intsts = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS); + intctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL); + ppsts = snd_sof_dsp_read(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPSTS); + rirbsts = snd_hdac_chip_readb(bus, RIRBSTS); + + dev_err(sdev->dev, + "error: hda irq intsts 0x%8.8x intlctl 0x%8.8x rirb %2.2x\n", + intsts, intctl, rirbsts); + dev_err(sdev->dev, + "error: dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n", + ppsts, adspis); +} + void hda_ipc_dump(struct snd_sof_dev *sdev) { u32 hipcie; u32 hipct; u32 hipcctl; + hda_ipc_irq_dump(sdev); + /* read IPC status */ hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE); hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 455046612b94..6c7dee2627d0 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -61,6 +61,7 @@ #define SOF_HDA_PP_CAP_ID 0x3 #define SOF_HDA_REG_PP_PPCH 0x10 #define SOF_HDA_REG_PP_PPCTL 0x04 +#define SOF_HDA_REG_PP_PPSTS 0x08 #define SOF_HDA_PPCTL_PIE BIT(31) #define SOF_HDA_PPCTL_GPROCEN BIT(30) @@ -449,6 +450,7 @@ void hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags); void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); void hda_ipc_dump(struct snd_sof_dev *sdev); +void hda_ipc_irq_dump(struct snd_sof_dev *sdev); /* * DSP PCM Operations. From e2eba551d2f4226400a6bb7871fef439ad1318dd Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 12 Jun 2019 11:57:04 -0500 Subject: [PATCH 370/626] ASoC: SOF: ignore unrecoverable CTX_SAVE IPC errors at suspend As part of the suspend flow, a context save IPC message is sent to the firmware before powering down the DSP. If errors are met, the suspend flow is aborted with current code. Change the behaviour such that if firmware returns -EBUSY or -EAGAIN, return the error codes to PM core as before. The device is left in active state in this case. If other errors are reported, print a warning but do not block the suspend flow. As per interface specification, no valid error can be returned in this scenario. If the hardware has hit a fatal error and is not able to respond successfully, best recovery method is to proceed with suspend and power off the DSP. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 8ef1d51025d8..b7843f02ef67 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -343,11 +343,20 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) #endif /* notify DSP of upcoming power down */ ret = sof_send_pm_ipc(sdev, SOF_IPC_PM_CTX_SAVE); - if (ret < 0) { + if (ret == -EBUSY || ret == -EAGAIN) { + /* + * runtime PM has logic to handle -EBUSY/-EAGAIN so + * pass these errors up + */ dev_err(sdev->dev, "error: ctx_save ipc error during suspend %d\n", ret); return ret; + } else if (ret < 0) { + /* FW in unexpected state, continue to power down */ + dev_warn(sdev->dev, + "ctx_save ipc error %d, proceeding with suspend\n", + ret); } /* power down all DSP cores */ From 847a040dd2ebb39effcc6bd3a5157fbded65bce7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 12 Jun 2019 11:57:05 -0500 Subject: [PATCH 371/626] ASoC: SOF: ipc: clarify operator precedence Cppcheck complains about the following warning, fix by adding parentheses [sound/soc/sof/ipc.c:783]: (style) Clarify calculation precedence for '&' and '?'. [sound/soc/sof/ipc.c:785]: (style) Clarify calculation precedence for '&' and '?'. [sound/soc/sof/ipc.c:787]: (style) Clarify calculation precedence for '&' and '?'. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index f3eb46bc808b..20dfca9c93b7 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -780,11 +780,11 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev) " lock debug: %s\n" " lock vdebug: %s\n", v->build, v->date, v->time, - ready->flags & SOF_IPC_INFO_GDB ? + (ready->flags & SOF_IPC_INFO_GDB) ? "enabled" : "disabled", - ready->flags & SOF_IPC_INFO_LOCKS ? + (ready->flags & SOF_IPC_INFO_LOCKS) ? "enabled" : "disabled", - ready->flags & SOF_IPC_INFO_LOCKSV ? + (ready->flags & SOF_IPC_INFO_LOCKSV) ? "enabled" : "disabled"); } From aa66fd80e0813fab0146e001b8bef8c4ffe0ba3a Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Wed, 12 Jun 2019 12:01:45 -0500 Subject: [PATCH 372/626] ASoC: SOF: topology: add min/max step for volume_table add two units min_volume_step and max_volume_step to the snd_sof_control struct, for the min and max step of the volume_table. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/sof-priv.h | 2 ++ sound/soc/sof/topology.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 17f3d2a5a701..8760a4694d8f 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -297,6 +297,8 @@ struct snd_sof_pcm { struct snd_sof_control { struct snd_sof_dev *sdev; int comp_id; + int min_volume_step; /* min volume step for volume_table */ + int max_volume_step; /* max volume step for volume_table */ int num_channels; u32 readback_offset; /* offset to mmaped data if used */ struct sof_ipc_ctrl_data *control_data; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index a13233ae6d0e..1c661dec8dd4 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -451,6 +451,8 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, return -ENOMEM; scontrol->comp_id = sdev->next_comp_id; + scontrol->min_volume_step = le32_to_cpu(mc->min); + scontrol->max_volume_step = le32_to_cpu(mc->max); scontrol->num_channels = le32_to_cpu(mc->num_channels); /* set cmd for mixer control */ From 65a18a46b274e64012fcf19d79ac62c8fb2a12e9 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Wed, 12 Jun 2019 12:01:46 -0500 Subject: [PATCH 373/626] ASoC: SOF: topology: pass volume min/max linear value to FW The driver currently passes the volume ramp type and length topology tokens to firmware, but the min and max volume are not set. This patch provides a correction to convert the information from the topology file and pass the linear volume min/max value to the firmware to improve transitions. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 1c661dec8dd4..bbad8053b1bc 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1552,6 +1552,9 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &tw->priv; struct sof_ipc_comp_volume *volume; + struct snd_sof_control *scontrol; + int min_step; + int max_step; int ret; volume = kzalloc(sizeof(*volume), GFP_KERNEL); @@ -1594,6 +1597,17 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index, swidget->private = volume; + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { + if (scontrol->comp_id == swidget->comp_id) { + min_step = scontrol->min_volume_step; + max_step = scontrol->max_volume_step; + volume->min_value = scontrol->volume_table[min_step]; + volume->max_value = scontrol->volume_table[max_step]; + volume->channels = scontrol->num_channels; + break; + } + } + ret = sof_ipc_tx_message(sdev->ipc, volume->comp.hdr.cmd, volume, sizeof(*volume), r, sizeof(*r)); if (ret >= 0) From 7df43911e92aa2137ae77ae60efaa9d6656df3fe Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Wed, 12 Jun 2019 12:01:47 -0500 Subject: [PATCH 374/626] ASoC: SOF: Add DMIC token for unmute gain ramp time The settling time of DMIC DC level is both platform and used microphone model specific. The unmute gain ramp is used to conceal most of the large DC level seen in beginning of capture. This patch adds into the DMIC DAI IPC struct a new field called unmute_ramp_time and a new token SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME. The value is the ramp length in milliseconds (ms). The ABI minor version is incremented for this backwards compatible change. Signed-off-by: Seppo Ingalsuo Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 3 ++- include/uapi/sound/sof/abi.h | 2 +- include/uapi/sound/sof/tokens.h | 1 + sound/soc/sof/topology.c | 4 ++++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 4bd83f7adddf..4bb8ee138ba7 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -167,9 +167,10 @@ struct sof_ipc_dai_dmic_params { uint32_t wake_up_time; /**< Time from clock start to data (us) */ uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */ + uint32_t unmute_ramp_time; /**< Length of logarithmic gain ramp (ms) */ /* reserved for future use */ - uint32_t reserved[6]; + uint32_t reserved[5]; /**< variable number of pdm controller config */ struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 92eee681bc62..4a9c24434f42 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 7 +#define SOF_ABI_MINOR 8 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 53ea94bf1c08..dc1b27daaac6 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -85,6 +85,7 @@ #define SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE 605 #define SOF_TKN_INTEL_DMIC_SAMPLE_RATE 608 #define SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH 609 +#define SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS 610 /* DMIC PDM */ #define SOF_TKN_INTEL_DMIC_PDM_CTRL_ID 700 diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index bbad8053b1bc..8e00f829bfdb 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -779,6 +779,10 @@ static const struct sof_topology_token dmic_tokens[] = { {SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, offsetof(struct sof_ipc_dai_dmic_params, fifo_bits), 0}, + {SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_dmic_params, unmute_ramp_time), 0}, + }; /* From 0c888baba8e041c92c5c1882f25b8df5c29bff9f Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 12 Jun 2019 12:01:48 -0500 Subject: [PATCH 375/626] ASoC: SOF: dont wake dsp up in kcontrol IO Always get kcontrol value from cache, set kcontrol value to DSP when DSP is active. Kcontrol values will be restored when DSP boot up. We will set the default value of kcontrol in sof_complete to make sure the value is align with firmware. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/control.c | 262 +++++---------------------------------- sound/soc/sof/topology.c | 48 +++++++ 2 files changed, 82 insertions(+), 228 deletions(-) diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 84e2cbfbbcbb..a4983f90ff5b 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -39,26 +39,8 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol, struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int err, ret; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: volume get failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } - - /* get all the mixer data from DSP */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_GET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_VOLUME, - false); /* read back each channel */ for (i = 0; i < channels; i++) @@ -66,12 +48,6 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol, ipc_to_mixer(cdata->chanv[i].value, scontrol->volume_table, sm->max + 1); - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: volume get failed to idle %d\n", - err); return 0; } @@ -84,16 +60,6 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int ret, err; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: volume put failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } /* update each channel */ for (i = 0; i < channels; i++) { @@ -104,18 +70,13 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, } /* notify DSP of mixer updates */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_SET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_VOLUME, - true); + if (pm_runtime_active(sdev->dev)) + snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_VALUE, + SOF_CTRL_TYPE_VALUE_CHAN_GET, + SOF_CTRL_CMD_VOLUME, + true); - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: volume put failed to idle %d\n", - err); return 0; } @@ -125,37 +86,13 @@ int snd_sof_switch_get(struct snd_kcontrol *kcontrol, struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int err, ret; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: switch get failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } - - /* get all the mixer data from DSP */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_GET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_SWITCH, - false); /* read back each channel */ for (i = 0; i < channels; i++) ucontrol->value.integer.value[i] = cdata->chanv[i].value; - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: switch get failed to idle %d\n", - err); return 0; } @@ -168,16 +105,6 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int ret, err; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: switch put failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } /* update each channel */ for (i = 0; i < channels; i++) { @@ -186,18 +113,13 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, } /* notify DSP of mixer updates */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_SET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_SWITCH, - true); + if (pm_runtime_active(sdev->dev)) + snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_VALUE, + SOF_CTRL_TYPE_VALUE_CHAN_GET, + SOF_CTRL_CMD_SWITCH, + true); - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: switch put failed to idle %d\n", - err); return 0; } @@ -207,37 +129,13 @@ int snd_sof_enum_get(struct snd_kcontrol *kcontrol, struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; struct snd_sof_control *scontrol = se->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int err, ret; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: enum get failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } - - /* get all the enum data from DSP */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_GET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_ENUM, - false); /* read back each channel */ for (i = 0; i < channels; i++) ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: enum get failed to idle %d\n", - err); return 0; } @@ -250,16 +148,6 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int ret, err; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: enum put failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } /* update each channel */ for (i = 0; i < channels; i++) { @@ -268,18 +156,13 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, } /* notify DSP of enum updates */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_SET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_ENUM, - true); + if (pm_runtime_active(sdev->dev)) + snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_VALUE, + SOF_CTRL_TYPE_VALUE_CHAN_GET, + SOF_CTRL_CMD_ENUM, + true); - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: enum put failed to idle %d\n", - err); return 0; } @@ -293,7 +176,7 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct sof_abi_hdr *data = cdata->data; size_t size; - int ret, err; + int ret = 0; if (be->max > sizeof(ucontrol->value.bytes.data)) { dev_err_ratelimited(sdev->dev, @@ -302,22 +185,6 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, return -EINVAL; } - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: bytes get failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } - - /* get all the binary data from DSP */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_GET_DATA, - SOF_CTRL_TYPE_DATA_GET, - scontrol->cmd, - false); - size = data->size + sizeof(*data); if (size > be->max) { dev_err_ratelimited(sdev->dev, @@ -331,12 +198,6 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, memcpy(ucontrol->value.bytes.data, data, size); out: - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: bytes get failed to idle %d\n", - err); return ret; } @@ -350,7 +211,6 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct sof_abi_hdr *data = cdata->data; size_t size = data->size + sizeof(*data); - int ret, err; if (be->max > sizeof(ucontrol->value.bytes.data)) { dev_err_ratelimited(sdev->dev, @@ -366,32 +226,18 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, return -EINVAL; } - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: bytes put failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } - /* copy from kcontrol */ memcpy(data, ucontrol->value.bytes.data, size); /* notify DSP of byte control updates */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_SET_DATA, - SOF_CTRL_TYPE_DATA_SET, - scontrol->cmd, - true); + if (pm_runtime_active(sdev->dev)) + snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_DATA, + SOF_CTRL_TYPE_DATA_SET, + scontrol->cmd, + true); - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: bytes put failed to idle %d\n", - err); - return ret; + return 0; } int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, @@ -406,8 +252,6 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, struct snd_ctl_tlv header; const struct snd_ctl_tlv __user *tlvd = (const struct snd_ctl_tlv __user *)binary_data; - int ret; - int err; /* * The beginning of bytes data contains a header from where @@ -453,30 +297,15 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, return -EINVAL; } - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: bytes_ext put failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } - /* notify DSP of byte control updates */ - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_SET_DATA, - SOF_CTRL_TYPE_DATA_SET, - scontrol->cmd, - true); + if (pm_runtime_active(sdev->dev)) + snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_DATA, + SOF_CTRL_TYPE_DATA_SET, + scontrol->cmd, + true); - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: bytes_ext put failed to idle %d\n", - err); - - return ret; + return 0; } int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, @@ -492,17 +321,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; int data_size; - int err; - int ret; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err_ratelimited(sdev->dev, - "error: bytes_ext get failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - return ret; - } + int ret = 0; /* * Decrement the limit by ext bytes header size to @@ -514,13 +333,6 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, cdata->data->magic = SOF_ABI_MAGIC; cdata->data->abi = SOF_ABI_VERSION; - /* get all the component data from DSP */ - ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_GET_DATA, - SOF_CTRL_TYPE_DATA_GET, - scontrol->cmd, - false); - /* Prevent read of other kernel data or possibly corrupt response */ data_size = cdata->data->size + sizeof(const struct sof_abi_hdr); @@ -543,11 +355,5 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, ret = -EFAULT; out: - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: bytes_ext get failed to idle %d\n", - err); return ret; } diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 8e00f829bfdb..aaf459af89d0 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3016,6 +3016,49 @@ err: return ret; } +/* Function to set the initial value of SOF kcontrols. + * The value will be stored in scontrol->control_data + */ +static int snd_sof_cache_kcontrol_val(struct snd_sof_dev *sdev) +{ + struct snd_sof_control *scontrol = NULL; + int ipc_cmd, ctrl_type; + int ret = 0; + + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { + + /* notify DSP of kcontrol values */ + switch (scontrol->cmd) { + case SOF_CTRL_CMD_VOLUME: + case SOF_CTRL_CMD_ENUM: + case SOF_CTRL_CMD_SWITCH: + ipc_cmd = SOF_IPC_COMP_GET_VALUE; + ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_GET; + break; + case SOF_CTRL_CMD_BINARY: + ipc_cmd = SOF_IPC_COMP_GET_DATA; + ctrl_type = SOF_CTRL_TYPE_DATA_GET; + break; + default: + dev_err(sdev->dev, + "error: Invalid scontrol->cmd: %d\n", + scontrol->cmd); + return -EINVAL; + } + ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + ipc_cmd, ctrl_type, + scontrol->cmd, + false); + if (ret < 0) { + dev_warn(sdev->dev, + "error: kcontrol value get for widget: %d\n", + scontrol->comp_id); + } + } + + return ret; +} + int snd_sof_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { @@ -3059,6 +3102,11 @@ static void sof_complete(struct snd_soc_component *scomp) break; } } + /* + * cache initial values of SOF kcontrols by reading DSP value over + * IPC. It may be overwritten by alsa-mixer after booting up + */ + snd_sof_cache_kcontrol_val(sdev); } /* manifest - optional to inform component of manifest */ From 7f807f280964e31fb32fe6aaa263cfa2488236d8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Jun 2019 11:47:54 +0200 Subject: [PATCH 376/626] ASoC: wm_adsp: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 37 +++++++------------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index b26e6b825a90..8f301cb07745 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -731,41 +731,18 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, struct dentry *root = NULL; int i; - if (!component->debugfs_root) { - adsp_err(dsp, "No codec debugfs root\n"); - goto err; - } - root = debugfs_create_dir(dsp->name, component->debugfs_root); - if (!root) - goto err; + debugfs_create_bool("booted", 0444, root, &dsp->booted); + debugfs_create_bool("running", 0444, root, &dsp->running); + debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id); + debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version); - if (!debugfs_create_bool("booted", 0444, root, &dsp->booted)) - goto err; - - if (!debugfs_create_bool("running", 0444, root, &dsp->running)) - goto err; - - if (!debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id)) - goto err; - - if (!debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version)) - goto err; - - for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) { - if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name, - 0444, root, dsp, - &wm_adsp_debugfs_fops[i].fops)) - goto err; - } + for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) + debugfs_create_file(wm_adsp_debugfs_fops[i].name, 0444, root, + dsp, &wm_adsp_debugfs_fops[i].fops); dsp->debugfs_root = root; - return; - -err: - debugfs_remove_recursive(root); - adsp_err(dsp, "Failed to create debugfs\n"); } static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) From 227ab8baa15bdd7a48acfb7b61c52a7a5eb87e72 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Jun 2019 11:47:55 +0200 Subject: [PATCH 377/626] ASoC: fsl: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 4 +--- sound/soc/fsl/fsl_ssi.h | 8 +++----- sound/soc/fsl/fsl_ssi_dbg.c | 18 ++++-------------- sound/soc/fsl/imx-audmux.c | 10 ++-------- 4 files changed, 10 insertions(+), 30 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 09b2967befd9..fa862af25c1a 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1582,9 +1582,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) } } - ret = fsl_ssi_debugfs_create(&ssi->dbg_stats, dev); - if (ret) - goto error_asoc_register; + fsl_ssi_debugfs_create(&ssi->dbg_stats, dev); /* Initially configures SSI registers */ fsl_ssi_hw_init(ssi); diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h index 0bdda608d414..db57cad80449 100644 --- a/sound/soc/fsl/fsl_ssi.h +++ b/sound/soc/fsl/fsl_ssi.h @@ -270,7 +270,6 @@ struct device; struct fsl_ssi_dbg { struct dentry *dbg_dir; - struct dentry *dbg_stats; struct { unsigned int rfrc; @@ -299,7 +298,7 @@ struct fsl_ssi_dbg { void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *ssi_dbg, u32 sisr); -int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev); +void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev); void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg); @@ -312,10 +311,9 @@ static inline void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *stats, u32 sisr) { } -static inline int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, - struct device *dev) +static inline void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, + struct device *dev) { - return 0; } static inline void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) diff --git a/sound/soc/fsl/fsl_ssi_dbg.c b/sound/soc/fsl/fsl_ssi_dbg.c index 6f6294149476..2a20ee23dc52 100644 --- a/sound/soc/fsl/fsl_ssi_dbg.c +++ b/sound/soc/fsl/fsl_ssi_dbg.c @@ -126,25 +126,15 @@ static int fsl_ssi_stats_show(struct seq_file *s, void *unused) DEFINE_SHOW_ATTRIBUTE(fsl_ssi_stats); -int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev) +void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev) { ssi_dbg->dbg_dir = debugfs_create_dir(dev_name(dev), NULL); - if (!ssi_dbg->dbg_dir) - return -ENOMEM; - ssi_dbg->dbg_stats = debugfs_create_file("stats", 0444, - ssi_dbg->dbg_dir, ssi_dbg, - &fsl_ssi_stats_fops); - if (!ssi_dbg->dbg_stats) { - debugfs_remove(ssi_dbg->dbg_dir); - return -ENOMEM; - } - - return 0; + debugfs_create_file("stats", 0444, ssi_dbg->dbg_dir, ssi_dbg, + &fsl_ssi_stats_fops); } void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) { - debugfs_remove(ssi_dbg->dbg_stats); - debugfs_remove(ssi_dbg->dbg_dir); + debugfs_remove_recursive(ssi_dbg->dbg_dir); } diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 04e59e66711d..b2351cd33b0f 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -141,17 +141,11 @@ static void audmux_debugfs_init(void) char buf[20]; audmux_debugfs_root = debugfs_create_dir("audmux", NULL); - if (!audmux_debugfs_root) { - pr_warning("Failed to create AUDMUX debugfs root\n"); - return; - } for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) { snprintf(buf, sizeof(buf), "ssi%lu", i); - if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, - (void *)i, &audmux_debugfs_fops)) - pr_warning("Failed to create AUDMUX port %lu debugfs file\n", - i); + debugfs_create_file(buf, 0444, audmux_debugfs_root, + (void *)i, &audmux_debugfs_fops); } } From abdcfc25641c5ba6d63047bec1dc8d3aaa7d4111 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 15 May 2019 15:18:56 +0200 Subject: [PATCH 378/626] ASoC: meson: add tohdmitx DT bindings Add the bindings and the related documentation for the audio hdmitx control glue of the Amlogic g12a SoC family Signed-off-by: Jerome Brunet Tested-by: Neil Armstrong Tested-by: Kevin Hilman Signed-off-by: Mark Brown --- .../bindings/sound/amlogic,g12a-tohdmitx.txt | 55 +++++++++++++++++++ .../dt-bindings/sound/meson-g12a-tohdmitx.h | 13 +++++ 2 files changed, 68 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt create mode 100644 include/dt-bindings/sound/meson-g12a-tohdmitx.h diff --git a/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt b/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt new file mode 100644 index 000000000000..aa6c35570d31 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt @@ -0,0 +1,55 @@ +* Amlogic HDMI Tx control glue + +Required properties: +- compatible: "amlogic,g12a-tohdmitx" +- reg: physical base address of the controller and length of memory + mapped region. +- #sound-dai-cells: should be 1. + +Example on the S905X2 SoC: + +tohdmitx: audio-controller@744 { + compatible = "amlogic,g12a-tohdmitx"; + reg = <0x0 0x744 0x0 0x4>; + #sound-dai-cells = <1>; +}; + +Example of an 'amlogic,axg-sound-card': + +sound { + compatible = "amlogic,axg-sound-card"; + +[...] + + dai-link-x { + sound-dai = <&tdmif_a>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-0 = <1 1>; + + codec-0 { + sound-dai = <&tohdmitx TOHDMITX_I2S_IN_A>; + }; + + codec-1 { + sound-dai = <&external_dac>; + }; + }; + + dai-link-y { + sound-dai = <&tdmif_c>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-0 = <1 1>; + + codec { + sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>; + }; + }; + + dai-link-z { + sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; + + codec { + sound-dai = <&hdmi_tx>; + }; + }; +}; diff --git a/include/dt-bindings/sound/meson-g12a-tohdmitx.h b/include/dt-bindings/sound/meson-g12a-tohdmitx.h new file mode 100644 index 000000000000..c5e1f48d30d0 --- /dev/null +++ b/include/dt-bindings/sound/meson-g12a-tohdmitx.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DT_MESON_G12A_TOHDMITX_H +#define __DT_MESON_G12A_TOHDMITX_H + +#define TOHDMITX_I2S_IN_A 0 +#define TOHDMITX_I2S_IN_B 1 +#define TOHDMITX_I2S_IN_C 2 +#define TOHDMITX_I2S_OUT 3 +#define TOHDMITX_SPDIF_IN_A 4 +#define TOHDMITX_SPDIF_IN_B 5 +#define TOHDMITX_SPDIF_OUT 6 + +#endif /* __DT_MESON_G12A_TOHDMITX_H */ From f69fc17947f1035459ebc55bc24f9b805dffba3d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 15 Jun 2019 18:10:56 +0900 Subject: [PATCH 379/626] ALSA: bebob: code rafactoring for callback functions to PCM interface The pairs of pcm.hw_params callback functions and .hw_free callback functions for both direction have no differences. This commit unifies the pairs. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_pcm.c | 55 ++++---------------------------- 1 file changed, 7 insertions(+), 48 deletions(-) diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 71b6ede31bb2..530db7a7844c 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -185,33 +185,8 @@ pcm_close(struct snd_pcm_substream *substream) return 0; } -static int -pcm_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_bebob *bebob = substream->private_data; - int err; - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { - unsigned int rate = params_rate(hw_params); - - mutex_lock(&bebob->mutex); - err = snd_bebob_stream_reserve_duplex(bebob, rate); - if (err >= 0) - ++bebob->substreams_counter; - mutex_unlock(&bebob->mutex); - } - - return err; -} -static int -pcm_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_bebob *bebob = substream->private_data; int err; @@ -234,23 +209,7 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, return err; } -static int -pcm_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_bebob *bebob = substream->private_data; - - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { - mutex_lock(&bebob->mutex); - bebob->substreams_counter--; - mutex_unlock(&bebob->mutex); - } - - snd_bebob_stream_stop_duplex(bebob); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} -static int -pcm_playback_hw_free(struct snd_pcm_substream *substream) +static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; @@ -360,8 +319,8 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_capture_hw_params, - .hw_free = pcm_capture_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, @@ -372,8 +331,8 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_playback_hw_params, - .hw_free = pcm_playback_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, From 73f7864eb5f00cc1a7a3936b5f7b170886851874 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 15 Jun 2019 18:10:57 +0900 Subject: [PATCH 380/626] ALSA: bebob: code refactoring for callback function to rawmidi interface The pairs of rawmidi.hw_params callback functions and .hw_free callback functions for both direction have no differences. This commit unifies the pairs. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_midi.c | 47 ++++--------------------------- 1 file changed, 6 insertions(+), 41 deletions(-) diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index e2d3cad39d28..f7db1f7bce86 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -8,7 +8,7 @@ #include "bebob.h" -static int midi_capture_open(struct snd_rawmidi_substream *substream) +static int midi_open(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data; int err; @@ -30,42 +30,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) return err; } -static int midi_playback_open(struct snd_rawmidi_substream *substream) -{ - struct snd_bebob *bebob = substream->rmidi->private_data; - int err; - - err = snd_bebob_stream_lock_try(bebob); - if (err < 0) - return err; - - mutex_lock(&bebob->mutex); - err = snd_bebob_stream_reserve_duplex(bebob, 0); - if (err >= 0) { - ++bebob->substreams_counter; - err = snd_bebob_stream_start_duplex(bebob); - } - mutex_unlock(&bebob->mutex); - if (err < 0) - snd_bebob_stream_lock_release(bebob); - - return err; -} - -static int midi_capture_close(struct snd_rawmidi_substream *substream) -{ - struct snd_bebob *bebob = substream->rmidi->private_data; - - mutex_lock(&bebob->mutex); - bebob->substreams_counter--; - snd_bebob_stream_stop_duplex(bebob); - mutex_unlock(&bebob->mutex); - - snd_bebob_stream_lock_release(bebob); - return 0; -} - -static int midi_playback_close(struct snd_rawmidi_substream *substream) +static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data; @@ -127,13 +92,13 @@ static void set_midi_substream_names(struct snd_bebob *bebob, int snd_bebob_create_midi_devices(struct snd_bebob *bebob) { static const struct snd_rawmidi_ops capture_ops = { - .open = midi_capture_open, - .close = midi_capture_close, + .open = midi_open, + .close = midi_close, .trigger = midi_capture_trigger, }; static const struct snd_rawmidi_ops playback_ops = { - .open = midi_playback_open, - .close = midi_playback_close, + .open = midi_open, + .close = midi_close, .trigger = midi_playback_trigger, }; struct snd_rawmidi *rmidi; From 5e818ac21f9d48a52955e68b96148a3b18f60c09 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 15 Jun 2019 18:10:58 +0900 Subject: [PATCH 381/626] ALSA: bebob: change the range of critical section for stream data in PCM.hw_free callback The operation of duplex streams should be in critical section. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_pcm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 530db7a7844c..e21de44deaa9 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -213,14 +213,15 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { - mutex_lock(&bebob->mutex); + mutex_lock(&bebob->mutex); + + if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) bebob->substreams_counter--; - mutex_unlock(&bebob->mutex); - } snd_bebob_stream_stop_duplex(bebob); + mutex_unlock(&bebob->mutex); + return snd_pcm_lib_free_vmalloc_buffer(substream); } From d173265ae36f8f6f76a507e2f529c351671269c0 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 15 Jun 2019 18:10:59 +0900 Subject: [PATCH 382/626] ALSA: bebob: code refactoring for error path to start duplex stream This commit removes useless procedures to stop packet streaming. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_stream.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 6aab3dc99bef..9ef4663d13e5 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -650,8 +650,6 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) if (!amdtp_stream_wait_callback(&bebob->rx_stream, CALLBACK_TIMEOUT)) { - amdtp_stream_stop(&bebob->rx_stream); - break_both_connections(bebob); err = -ETIMEDOUT; goto error; } From c6b84ffbd5e78d6cf4aaafe5502e1bc99eb9657c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 15 Jun 2019 18:11:00 +0900 Subject: [PATCH 383/626] ALSA: fireworks: change the range of critical section for stream data in PCM.hw_free callback The operation of duplex streams should be in critical section. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_pcm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 287fc05d5917..8dc34249a1b0 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -247,14 +247,15 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { - mutex_lock(&efw->mutex); + mutex_lock(&efw->mutex); + + if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) --efw->substreams_counter; - mutex_unlock(&efw->mutex); - } snd_efw_stream_stop_duplex(efw); + mutex_unlock(&efw->mutex); + return snd_pcm_lib_free_vmalloc_buffer(substream); } From 7bc93821a70adc621df443c8b7a4745023c36e7c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 15 Jun 2019 18:11:01 +0900 Subject: [PATCH 384/626] ALSA: firewire-lib: split allocation of isochronous resources from establishment of connection In current implementation, establishment connection corresponds to allocation of isochronous resources. Although this is an ideal implementation of CMP described in IEC 61883-1, it's not enough efficient to recover PCM substream multiplexed in packet streaming. The packet streaming can always restart on the same allocated isochronous resources even if the previous packet streaming corrupted. This commit splits allocation of isochronous resources from establishment of connection so that CMP runs with allocated isochronous resources. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_stream.c | 30 ++++++--- sound/firewire/cmp.c | 74 ++++++++++++--------- sound/firewire/cmp.h | 7 +- sound/firewire/fireworks/fireworks_stream.c | 22 ++++-- sound/firewire/oxfw/oxfw-stream.c | 18 +++-- 5 files changed, 100 insertions(+), 51 deletions(-) diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 9ef4663d13e5..1070a675179d 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -404,13 +404,11 @@ static int make_both_connections(struct snd_bebob *bebob) { int err = 0; - err = cmp_connection_establish(&bebob->out_conn, - amdtp_stream_get_max_payload(&bebob->tx_stream)); + err = cmp_connection_establish(&bebob->out_conn); if (err < 0) return err; - err = cmp_connection_establish(&bebob->in_conn, - amdtp_stream_get_max_payload(&bebob->rx_stream)); + err = cmp_connection_establish(&bebob->in_conn); if (err < 0) { cmp_connection_break(&bebob->out_conn); return err; @@ -533,14 +531,23 @@ static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, unsigned int rate, unsigned int index) { struct snd_bebob_stream_formation *formation; + struct cmp_connection *conn; + int err; - if (stream == &bebob->tx_stream) + if (stream == &bebob->tx_stream) { formation = bebob->tx_stream_formations + index; - else + conn = &bebob->out_conn; + } else { formation = bebob->rx_stream_formations + index; + conn = &bebob->in_conn; + } - return amdtp_am824_set_parameters(stream, rate, formation->pcm, - formation->midi, false); + err = amdtp_am824_set_parameters(stream, rate, formation->pcm, + formation->midi, false); + if (err < 0) + return err; + + return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); } int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) @@ -591,8 +598,10 @@ int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) return err; err = keep_resources(bebob, &bebob->rx_stream, rate, index); - if (err < 0) + if (err < 0) { + cmp_connection_release(&bebob->out_conn); return err; + } } return 0; @@ -685,6 +694,9 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) amdtp_stream_stop(&bebob->tx_stream); break_both_connections(bebob); + + cmp_connection_release(&bebob->out_conn); + cmp_connection_release(&bebob->in_conn); } } diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index ae3bc1940efa..5dedc4f31842 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c @@ -185,6 +185,37 @@ void cmp_connection_destroy(struct cmp_connection *c) } EXPORT_SYMBOL(cmp_connection_destroy); +int cmp_connection_reserve(struct cmp_connection *c, + unsigned int max_payload_bytes) +{ + int err; + + mutex_lock(&c->mutex); + + if (WARN_ON(c->resources.allocated)) { + err = -EBUSY; + goto end; + } + + c->speed = min(c->max_speed, + fw_parent_device(c->resources.unit)->max_speed); + + err = fw_iso_resources_allocate(&c->resources, max_payload_bytes, + c->speed); +end: + mutex_unlock(&c->mutex); + + return err; +} +EXPORT_SYMBOL(cmp_connection_reserve); + +void cmp_connection_release(struct cmp_connection *c) +{ + mutex_lock(&c->mutex); + fw_iso_resources_free(&c->resources); + mutex_unlock(&c->mutex); +} +EXPORT_SYMBOL(cmp_connection_release); static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) { @@ -270,25 +301,18 @@ static int pcr_set_check(struct cmp_connection *c, __be32 pcr) * When this function succeeds, the caller is responsible for starting * transmitting packets. */ -int cmp_connection_establish(struct cmp_connection *c, - unsigned int max_payload_bytes) +int cmp_connection_establish(struct cmp_connection *c) { int err; - if (WARN_ON(c->connected)) - return -EISCONN; - - c->speed = min(c->max_speed, - fw_parent_device(c->resources.unit)->max_speed); - mutex_lock(&c->mutex); -retry_after_bus_reset: - err = fw_iso_resources_allocate(&c->resources, - max_payload_bytes, c->speed); - if (err < 0) - goto err_mutex; + if (WARN_ON(c->connected)) { + mutex_unlock(&c->mutex); + return -EISCONN; + } +retry_after_bus_reset: if (c->direction == CMP_OUTPUT) err = pcr_modify(c, opcr_set_modify, pcr_set_check, ABORT_ON_BUS_RESET); @@ -297,21 +321,13 @@ retry_after_bus_reset: ABORT_ON_BUS_RESET); if (err == -EAGAIN) { - fw_iso_resources_free(&c->resources); - goto retry_after_bus_reset; + err = fw_iso_resources_update(&c->resources); + if (err >= 0) + goto retry_after_bus_reset; } - if (err < 0) - goto err_resources; + if (err >= 0) + c->connected = true; - c->connected = true; - - mutex_unlock(&c->mutex); - - return 0; - -err_resources: - fw_iso_resources_free(&c->resources); -err_mutex: mutex_unlock(&c->mutex); return err; @@ -351,14 +367,12 @@ int cmp_connection_update(struct cmp_connection *c) SUCCEED_ON_BUS_RESET); if (err < 0) - goto err_resources; + goto err_unconnect; mutex_unlock(&c->mutex); return 0; -err_resources: - fw_iso_resources_free(&c->resources); err_unconnect: c->connected = false; mutex_unlock(&c->mutex); @@ -395,8 +409,6 @@ void cmp_connection_break(struct cmp_connection *c) if (err < 0) cmp_error(c, "plug is still connected\n"); - fw_iso_resources_free(&c->resources); - c->connected = false; mutex_unlock(&c->mutex); diff --git a/sound/firewire/cmp.h b/sound/firewire/cmp.h index b60b415caa8f..26ab88000e34 100644 --- a/sound/firewire/cmp.h +++ b/sound/firewire/cmp.h @@ -42,8 +42,11 @@ int cmp_connection_init(struct cmp_connection *connection, int cmp_connection_check_used(struct cmp_connection *connection, bool *used); void cmp_connection_destroy(struct cmp_connection *connection); -int cmp_connection_establish(struct cmp_connection *connection, - unsigned int max_payload); +int cmp_connection_reserve(struct cmp_connection *connection, + unsigned int max_payload); +void cmp_connection_release(struct cmp_connection *connection); + +int cmp_connection_establish(struct cmp_connection *connection); int cmp_connection_update(struct cmp_connection *connection); void cmp_connection_break(struct cmp_connection *connection); diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 61342c49dc38..81c1bb209a89 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -63,8 +63,7 @@ static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, conn = &efw->in_conn; // Establish connection via CMP. - err = cmp_connection_establish(conn, - amdtp_stream_get_max_payload(stream)); + err = cmp_connection_establish(conn); if (err < 0) return err; @@ -177,17 +176,25 @@ static int keep_resources(struct snd_efw *efw, struct amdtp_stream *stream, { unsigned int pcm_channels; unsigned int midi_ports; + struct cmp_connection *conn; + int err; if (stream == &efw->tx_stream) { pcm_channels = efw->pcm_capture_channels[mode]; midi_ports = efw->midi_out_ports; + conn = &efw->out_conn; } else { pcm_channels = efw->pcm_playback_channels[mode]; midi_ports = efw->midi_in_ports; + conn = &efw->in_conn; } - return amdtp_am824_set_parameters(stream, rate, pcm_channels, - midi_ports, false); + err = amdtp_am824_set_parameters(stream, rate, pcm_channels, + midi_ports, false); + if (err < 0) + return err; + + return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); } int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) @@ -228,8 +235,10 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) return err; err = keep_resources(efw, &efw->rx_stream, rate, mode); - if (err < 0) + if (err < 0) { + cmp_connection_release(&efw->in_conn); return err; + } } return 0; @@ -285,6 +294,9 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw) if (efw->substreams_counter == 0) { stop_stream(efw, &efw->tx_stream); stop_stream(efw, &efw->rx_stream); + + cmp_connection_release(&efw->out_conn); + cmp_connection_release(&efw->in_conn); } } diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 837733f10736..a8bc798731ff 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -111,8 +111,7 @@ static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) else conn = &oxfw->out_conn; - err = cmp_connection_establish(conn, - amdtp_stream_get_max_payload(stream)); + err = cmp_connection_establish(conn); if (err < 0) return err; @@ -203,15 +202,18 @@ static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream) enum avc_general_plug_dir dir; u8 **formats; struct snd_oxfw_stream_formation formation; + struct cmp_connection *conn; int i; int err; if (stream == &oxfw->rx_stream) { dir = AVC_GENERAL_PLUG_DIR_IN; formats = oxfw->rx_stream_formats; + conn = &oxfw->in_conn; } else { dir = AVC_GENERAL_PLUG_DIR_OUT; formats = oxfw->tx_stream_formats; + conn = &oxfw->out_conn; } err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); @@ -239,8 +241,12 @@ static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream) if (formation.pcm == 0) return -EINVAL; - return amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, + err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, formation.midi * 8, false); + if (err < 0) + return err; + + return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); } int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, @@ -299,8 +305,10 @@ int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, if (oxfw->has_output) { err = keep_resources(oxfw, &oxfw->tx_stream); - if (err < 0) + if (err < 0) { + cmp_connection_release(&oxfw->in_conn); return err; + } } } @@ -361,10 +369,12 @@ void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw) if (oxfw->substreams_count == 0) { amdtp_stream_stop(&oxfw->rx_stream); cmp_connection_break(&oxfw->in_conn); + cmp_connection_release(&oxfw->in_conn); if (oxfw->has_output) { amdtp_stream_stop(&oxfw->tx_stream); cmp_connection_break(&oxfw->out_conn); + cmp_connection_release(&oxfw->out_conn); } } } From 41d92e0c835bff7dec343bf41e79d24b326d94c1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 17 Jun 2019 13:03:51 +0200 Subject: [PATCH 385/626] ASoC: rockchip: pdm: select CONFIG_RATIONAL Without this, we get a link error: sound/soc/rockchip/rockchip_pdm.o: In function `rockchip_pdm_hw_params': rockchip_pdm.c:(.text+0x754): undefined reference to `rational_best_approximation' Fixes: 624e8e00acaf ("ASoC: rockchip: pdm: fixup pdm fractional div") Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- sound/soc/rockchip/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index 957046ac6c8c..d88555e0c389 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -19,6 +19,7 @@ config SND_SOC_ROCKCHIP_PDM tristate "Rockchip PDM Controller Driver" depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP select SND_SOC_GENERIC_DMAENGINE_PCM + select RATIONAL help Say Y or M if you want to add support for PDM driver for Rockchip PDM Controller. The Controller supports up to maximum of From 83ee240aad9147ed5dac5a7c7b4c559d134072e7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 17 Jun 2019 13:06:15 +0200 Subject: [PATCH 386/626] ASoC: cx2072x: mark PM function as __maybe_unused While the suspend function is already marked __maybe_unused, the resume function is not, which leads to a warning when CONFIG_PM is disabled: sound/soc/codecs/cx2072x.c:1625:12: error: unused function 'cx2072x_runtime_resume' [-Werror,-Wunused-function] Mark this one like the other one. Fixes: a497a4363706 ("ASoC: Add support for Conexant CX2072X CODEC") Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index f2cb35a50726..1c1ba7bea4d8 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1622,7 +1622,7 @@ static int __maybe_unused cx2072x_runtime_suspend(struct device *dev) return 0; } -static int cx2072x_runtime_resume(struct device *dev) +static int __maybe_unused cx2072x_runtime_resume(struct device *dev) { struct cx2072x_priv *cx2072x = dev_get_drvdata(dev); From 7623ae793c28cc0928c5d1292542dbb92fc2e9e2 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:33 -0500 Subject: [PATCH 387/626] ASoC: SOF: Intel: hda: save handle to sdev in sof_intel_hda_stream Add a snd_sof_dev member to sof_intel_hda_stream. This will be used to access the snd_sof_dev during link hw_params callback. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 4 ++++ sound/soc/sof/intel/hda.h | 1 + 2 files changed, 5 insertions(+) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index c92006f89499..1cd94e7631a8 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -564,6 +564,8 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) if (!hda_stream) return -ENOMEM; + hda_stream->sdev = sdev; + stream = &hda_stream->hda_stream; stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + @@ -617,6 +619,8 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) if (!hda_stream) return -ENOMEM; + hda_stream->sdev = sdev; + stream = &hda_stream->hda_stream; /* we always have DSP support */ diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 6c7dee2627d0..502b0a3c2e3c 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -409,6 +409,7 @@ static inline struct hda_bus *sof_to_hbus(struct snd_sof_dev *s) } struct sof_intel_hda_stream { + struct snd_sof_dev *sdev; struct hdac_ext_stream hda_stream; struct sof_intel_stream stream; int hw_params_upon_resume; /* set up hw_params upon resume */ From f5dbba9fee801f4678a50d92c785f7f24d4ee2c6 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:34 -0500 Subject: [PATCH 388/626] ASoC: SOF: Intel: hda: add new macro hstream_to_sof_hda_stream() Add a new macro to get sof_intel_hda_stream from hdac_ext_stream. Signed-off-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 502b0a3c2e3c..376b1ca51e2b 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -415,6 +415,9 @@ struct sof_intel_hda_stream { int hw_params_upon_resume; /* set up hw_params upon resume */ }; +#define hstream_to_sof_hda_stream(hstream) \ + container_of(hstream, struct sof_intel_hda_stream, hda_stream) + #define bus_to_sof_hda(bus) \ container_of(bus, struct sof_intel_hda_dev, hbus.core) From 1b7e1956860d7566325502651c6bf14f115cd91d Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:35 -0500 Subject: [PATCH 389/626] ASoC: SOF: topology: add cpu_dai_name for DAIs Add the cpu_dai_name member to snd_sof_dai and save the cpu_dai_name while setting the DAI config. The internal SOF representation will have to change at a later point as well when we have multiple CPU dais. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/sof-priv.h | 1 + sound/soc/sof/topology.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 8760a4694d8f..8c3ac149bbb9 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -337,6 +337,7 @@ struct snd_sof_route { struct snd_sof_dai { struct snd_sof_dev *sdev; const char *name; + const char *cpu_dai_name; struct sof_ipc_comp_dai comp_dai; struct sof_ipc_dai_config *dai_config; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index aaf459af89d0..178256e338b1 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2360,6 +2360,9 @@ static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, if (!dai->dai_config) return -ENOMEM; + /* set cpu_dai_name */ + dai->cpu_dai_name = link->cpus->dai_name; + found = 1; } } @@ -2624,6 +2627,8 @@ static int sof_link_hda_process(struct snd_sof_dev *sdev, if (!sof_dai->dai_config) return -ENOMEM; + sof_dai->cpu_dai_name = link->cpus->dai_name; + /* send message to DSP */ ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, From bdf4ad3fd01f5dc53c5d6d3b17afc98cd76d8988 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:36 -0500 Subject: [PATCH 390/626] ASoC: SOF: Intel: hda: assign link DMA channel at run-time The recommended HDA HW programming sequence for setting the DMA format requires that the link DMA and host DMA channels be coupled before setting the format. This change means that host DMA or link DMA channels be reserved even if only one is used. Statically assigned link DMA channels would mean that all the corresponding host DMA channels will need to be reserved, leaving only a few channels available at run-time. So, the suggestion here is to switch to dynamically assigning both host DMA channels and link DMA channels are run-time. The host DMA channel is assigned when the pcm is opened as before. While choosing the link DMA channel, if the host DMA channel corresponding to the link DMA channel is already taken, the proposed method checks to make sure that the BE is connected to the FE that has been assigned this host DMA channel. Once the link DMA channel is assigned, an IPC is sent to the DSP to set the link DMA channel. The link DMA channel is freed during hw_free() and also in the SUSPEND trigger callback. It will be re-assigned when hw_params are set upon resume. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 282 ++++++++++++++++++++++------------ sound/soc/sof/sof-priv.h | 2 + sound/soc/sof/topology.c | 51 +----- 3 files changed, 188 insertions(+), 147 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index e1decf25aeac..c270fd7a0878 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -30,62 +30,84 @@ struct hda_pipe_params { }; /* - * Unlike GP dma, there is a set of stream registers in hda controller - * to control the link dma channels. Each register controls one link - * dma channel and the relation is fixed. To make sure FW uses correct - * link dma channels, host allocates stream registers and sends the - * corresponding link dma channels to FW to allocate link dma channel - * - * FIXME: this API is abused in the sense that tx_num and rx_num are - * passed as arguments, not returned. We need to find a better way to - * retrieve the stream tag allocated for the link DMA + * This function checks if the host dma channel corresponding + * to the link DMA stream_tag argument is assigned to one + * of the FEs connected to the BE DAI. */ -static int hda_link_dma_get_channels(struct snd_soc_dai *dai, - unsigned int *tx_num, - unsigned int *tx_slot, - unsigned int *rx_num, - unsigned int *rx_slot) +static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd, + int dir, int stream_tag) { - struct hdac_bus *bus; - struct hdac_ext_stream *stream; - struct snd_pcm_substream substream; - struct snd_sof_dev *sdev = - snd_soc_component_get_drvdata(dai->component); + struct snd_pcm_substream *fe_substream; + struct hdac_stream *fe_hstream; + struct snd_soc_dpcm *dpcm; - bus = sof_to_bus(sdev); - - memset(&substream, 0, sizeof(substream)); - if (*tx_num == 1) { - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; - stream = snd_hdac_ext_stream_assign(bus, &substream, - HDAC_EXT_STREAM_TYPE_LINK); - if (!stream) { - dev_err(bus->dev, "error: failed to find a free hda ext stream for playback"); - return -EBUSY; - } - - snd_soc_dai_set_dma_data(dai, &substream, stream); - *tx_slot = hdac_stream(stream)->stream_tag - 1; - - dev_dbg(bus->dev, "link dma channel %d for playback", *tx_slot); + for_each_dpcm_fe(rtd, dir, dpcm) { + fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir); + fe_hstream = fe_substream->runtime->private_data; + if (fe_hstream->stream_tag == stream_tag) + return true; } - if (*rx_num == 1) { - substream.stream = SNDRV_PCM_STREAM_CAPTURE; - stream = snd_hdac_ext_stream_assign(bus, &substream, - HDAC_EXT_STREAM_TYPE_LINK); - if (!stream) { - dev_err(bus->dev, "error: failed to find a free hda ext stream for capture"); - return -EBUSY; - } + return false; +} - snd_soc_dai_set_dma_data(dai, &substream, stream); - *rx_slot = hdac_stream(stream)->stream_tag - 1; +static struct hdac_ext_stream * + hda_link_stream_assign(struct hdac_bus *bus, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sof_intel_hda_stream *hda_stream; + struct hdac_ext_stream *res = NULL; + struct hdac_stream *stream = NULL; - dev_dbg(bus->dev, "link dma channel %d for capture", *rx_slot); + int stream_dir = substream->stream; + + if (!bus->ppcap) { + dev_err(bus->dev, "stream type not supported\n"); + return NULL; } - return 0; + list_for_each_entry(stream, &bus->stream_list, list) { + struct hdac_ext_stream *hstream = + stream_to_hdac_ext_stream(stream); + if (stream->direction != substream->stream) + continue; + + hda_stream = hstream_to_sof_hda_stream(hstream); + + /* check if available */ + if (!hstream->link_locked) { + if (stream->opened) { + /* + * check if the stream tag matches the stream + * tag of one of the connected FEs + */ + if (hda_check_fes(rtd, stream_dir, + stream->stream_tag)) { + res = hstream; + break; + } + } else { + res = hstream; + break; + } + } + } + + if (res) { + /* + * Decouple host and link DMA. The decoupled flag + * is updated in snd_hdac_ext_stream_decouple(). + */ + if (!res->decoupled) + snd_hdac_ext_stream_decouple(bus, res, true); + spin_lock_irq(&bus->reg_lock); + res->link_locked = 1; + res->link_substream = substream; + spin_unlock_irq(&bus->reg_lock); + } + + return res; } static int hda_link_dma_params(struct hdac_ext_stream *stream, @@ -122,6 +144,51 @@ static int hda_link_dma_params(struct hdac_ext_stream *stream, return 0; } +/* Send DAI_CONFIG IPC to the DAI that matches the dai_name and direction */ +static int hda_link_config_ipc(struct sof_intel_hda_stream *hda_stream, + const char *dai_name, int channel, int dir) +{ + struct sof_ipc_dai_config *config; + struct snd_sof_dai *sof_dai; + struct sof_ipc_reply reply; + int ret = 0; + + list_for_each_entry(sof_dai, &hda_stream->sdev->dai_list, list) { + if (!sof_dai->cpu_dai_name) + continue; + + if (!strcmp(dai_name, sof_dai->cpu_dai_name) && + dir == sof_dai->comp_dai.direction) { + config = sof_dai->dai_config; + + if (!config) { + dev_err(hda_stream->sdev->dev, + "error: no config for DAI %s\n", + sof_dai->name); + return -EINVAL; + } + + /* update config with stream tag */ + config->hda.link_dma_ch = channel; + + /* send IPC */ + ret = sof_ipc_tx_message(hda_stream->sdev->ipc, + config->hdr.cmd, + config, + config->hdr.size, + &reply, sizeof(reply)); + + if (ret < 0) + dev_err(hda_stream->sdev->dev, + "error: failed to set dai config for %s\n", + sof_dai->name); + return ret; + } + } + + return -EINVAL; +} + static int hda_link_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -135,20 +202,31 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, struct hda_pipe_params p_params = {0}; struct hdac_ext_link *link; int stream_tag; + int ret; - link_dev = snd_soc_dai_get_dma_data(dai, substream); + link_dev = hda_link_stream_assign(bus, substream); + if (!link_dev) + return -EBUSY; + + stream_tag = hdac_stream(link_dev)->stream_tag; + + hda_stream = hstream_to_sof_hda_stream(link_dev); + + /* update the DSP with the new tag */ + ret = hda_link_config_ipc(hda_stream, dai->name, stream_tag - 1, + substream->stream); + if (ret < 0) + return ret; + + snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); - hda_stream = container_of(link_dev, struct sof_intel_hda_stream, - hda_stream); hda_stream->hw_params_upon_resume = 0; link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name); if (!link) return -EINVAL; - stream_tag = hdac_stream(link_dev)->stream_tag; - - /* set the stream tag in the codec dai dma params */ + /* set the stream tag in the codec dai dma params */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0); else @@ -181,8 +259,7 @@ static int hda_link_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); int stream = substream->stream; - hda_stream = container_of(link_dev, struct sof_intel_hda_stream, - hda_stream); + hda_stream = hstream_to_sof_hda_stream(link_dev); /* setup hw_params again only if resuming from system suspend */ if (!hda_stream->hw_params_upon_resume) @@ -199,8 +276,24 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, { struct hdac_ext_stream *link_dev = snd_soc_dai_get_dma_data(dai, substream); + struct sof_intel_hda_stream *hda_stream; + struct snd_soc_pcm_runtime *rtd; + struct hdac_ext_link *link; + struct hdac_stream *hstream; + struct hdac_bus *bus; + int stream_tag; int ret; + hstream = substream->runtime->private_data; + bus = hstream->bus; + rtd = snd_pcm_substream_chip(substream); + + link = snd_hdac_ext_bus_get_link(bus, rtd->codec_dai->component->name); + if (!link) + return -EINVAL; + + hda_stream = hstream_to_sof_hda_stream(link_dev); + dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: @@ -217,8 +310,22 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_hdac_ext_link_stream_start(link_dev); break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: + /* + * clear and release link DMA channel. It will be assigned when + * hw_params is set up again after resume. + */ + ret = hda_link_config_ipc(hda_stream, dai->name, + DMA_CHAN_INVALID, substream->stream); + if (ret < 0) + return ret; + stream_tag = hdac_stream(link_dev)->stream_tag; + snd_hdac_ext_link_clear_stream_id(link, stream_tag); + snd_hdac_ext_stream_release(link_dev, + HDAC_EXT_STREAM_TYPE_LINK); + + /* fallthrough */ + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_STOP: snd_hdac_ext_link_stream_clear(link_dev); break; @@ -228,62 +335,38 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, return 0; } -/* - * FIXME: This API is also abused since it's used for two purposes. - * when the substream argument is NULL this function is used for cleanups - * that aren't necessarily required, and called explicitly by handling - * ASoC core structures, which is not recommended. - * This part will be reworked in follow-up patches. - */ static int hda_link_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - const char *name; unsigned int stream_tag; + struct sof_intel_hda_stream *hda_stream; struct hdac_bus *bus; struct hdac_ext_link *link; struct hdac_stream *hstream; - struct hdac_ext_stream *stream; struct snd_soc_pcm_runtime *rtd; struct hdac_ext_stream *link_dev; - struct snd_pcm_substream pcm_substream; + int ret; - memset(&pcm_substream, 0, sizeof(pcm_substream)); - if (substream) { - hstream = substream->runtime->private_data; - bus = hstream->bus; - rtd = snd_pcm_substream_chip(substream); - link_dev = snd_soc_dai_get_dma_data(dai, substream); - snd_hdac_ext_stream_decouple(bus, link_dev, false); - name = rtd->codec_dai->component->name; - link = snd_hdac_ext_bus_get_link(bus, name); - if (!link) - return -EINVAL; + hstream = substream->runtime->private_data; + bus = hstream->bus; + rtd = snd_pcm_substream_chip(substream); + link_dev = snd_soc_dai_get_dma_data(dai, substream); + hda_stream = hstream_to_sof_hda_stream(link_dev); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - stream_tag = hdac_stream(link_dev)->stream_tag; - snd_hdac_ext_link_clear_stream_id(link, stream_tag); - } + /* free the link DMA channel in the FW */ + ret = hda_link_config_ipc(hda_stream, dai->name, DMA_CHAN_INVALID, + substream->stream); + if (ret < 0) + return ret; - link_dev->link_prepared = 0; - } else { - /* release all hda streams when dai link is unloaded */ - pcm_substream.stream = SNDRV_PCM_STREAM_PLAYBACK; - stream = snd_soc_dai_get_dma_data(dai, &pcm_substream); - if (stream) { - snd_soc_dai_set_dma_data(dai, &pcm_substream, NULL); - snd_hdac_ext_stream_release(stream, - HDAC_EXT_STREAM_TYPE_LINK); - } + link = snd_hdac_ext_bus_get_link(bus, rtd->codec_dai->component->name); + if (!link) + return -EINVAL; - pcm_substream.stream = SNDRV_PCM_STREAM_CAPTURE; - stream = snd_soc_dai_get_dma_data(dai, &pcm_substream); - if (stream) { - snd_soc_dai_set_dma_data(dai, &pcm_substream, NULL); - snd_hdac_ext_stream_release(stream, - HDAC_EXT_STREAM_TYPE_LINK); - } - } + stream_tag = hdac_stream(link_dev)->stream_tag; + snd_hdac_ext_link_clear_stream_id(link, stream_tag); + snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); + link_dev->link_prepared = 0; return 0; } @@ -293,7 +376,6 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = { .hw_free = hda_link_hw_free, .trigger = hda_link_pcm_trigger, .prepare = hda_link_pcm_prepare, - .get_channel_map = hda_link_dma_get_channels, }; #endif diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 8c3ac149bbb9..b80d93e5df2f 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -60,6 +60,8 @@ (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) || \ IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)) +#define DMA_CHAN_INVALID 0xFFFFFFFF + struct snd_sof_dev; struct snd_sof_ipc_msg; struct snd_sof_ipc; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 178256e338b1..432ae343f960 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2591,9 +2591,7 @@ err: */ static int sof_link_hda_process(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link, - struct sof_ipc_dai_config *config, - int tx_slot, - int rx_slot) + struct sof_ipc_dai_config *config) { struct sof_ipc_reply reply; u32 size = sizeof(*config); @@ -2606,22 +2604,11 @@ static int sof_link_hda_process(struct snd_sof_dev *sdev, continue; if (strcmp(link->name, sof_dai->name) == 0) { - if (sof_dai->comp_dai.direction == - SNDRV_PCM_STREAM_PLAYBACK) { - if (!link->dpcm_playback) - return -EINVAL; - - config->hda.link_dma_ch = tx_slot; - } else { - if (!link->dpcm_capture) - return -EINVAL; - - config->hda.link_dma_ch = rx_slot; - } - config->dai_index = sof_dai->comp_dai.dai_index; found = 1; + config->hda.link_dma_ch = DMA_CHAN_INVALID; + /* save config in dai component */ sof_dai->dai_config = kmemdup(config, size, GFP_KERNEL); if (!sof_dai->dai_config) @@ -2667,10 +2654,6 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_private *private = &cfg->priv; struct snd_soc_dai *dai; u32 size = sizeof(*config); - u32 tx_num = 0; - u32 tx_slot = 0; - u32 rx_num = 0; - u32 rx_slot = 0; int ret; /* init IPC */ @@ -2694,22 +2677,7 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, return -EINVAL; } - if (link->dpcm_playback) - tx_num = 1; - - if (link->dpcm_capture) - rx_num = 1; - - ret = snd_soc_dai_get_channel_map(dai, &tx_num, &tx_slot, - &rx_num, &rx_slot); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to get dma channel for HDA%d\n", - config->dai_index); - - return ret; - } - - ret = sof_link_hda_process(sdev, link, config, tx_slot, rx_slot); + ret = sof_link_hda_process(sdev, link, config); if (ret < 0) dev_err(sdev->dev, "error: failed to process hda dai link %s", link->name); @@ -2837,17 +2805,6 @@ static int sof_link_hda_unload(struct snd_sof_dev *sdev, return -EINVAL; } - /* - * FIXME: this call to hw_free is mainly to release the link DMA ID. - * This is abusing the API and handling SOC internals is not - * recommended. This part will be reworked. - */ - if (dai->driver->ops->hw_free) - ret = dai->driver->ops->hw_free(NULL, dai); - if (ret < 0) - dev_err(sdev->dev, "error: failed to free hda resource for %s\n", - link->name); - return ret; } From 6b2239e3337b4c46b850078a6fc8f1a70ebe1c1f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:37 -0500 Subject: [PATCH 391/626] ASoC: SOF: Intel: hda: reserve host DMA channel for hostless streams Due to the HW programming sequence requirement that the host and link DMA channels need to be coupled/decoupled during pcm hw_params, the host DMA channel corresponding to the link DMA channel in use for hostless streams needs to be reserved. This is achieved by adding a host_reserved flag in the sof_intel_hda_stream structure which is checked when assigning a host DMA channel. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 11 ++++++++++- sound/soc/sof/intel/hda-stream.c | 10 +++++++++- sound/soc/sof/intel/hda.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c270fd7a0878..a514f9cf5c9a 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -75,7 +75,7 @@ static struct hdac_ext_stream * hda_stream = hstream_to_sof_hda_stream(hstream); - /* check if available */ + /* check if link is available */ if (!hstream->link_locked) { if (stream->opened) { /* @@ -89,6 +89,12 @@ static struct hdac_ext_stream * } } else { res = hstream; + + /* + * This must be a hostless stream. + * So reserve the host DMA channel. + */ + hda_stream->host_reserved = 1; break; } } @@ -368,6 +374,9 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream, snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); link_dev->link_prepared = 0; + /* free the host DMA channel reserved by hostless streams */ + hda_stream->host_reserved = 0; + return 0; } diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 1cd94e7631a8..a3f7c91469ec 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -155,6 +155,7 @@ struct hdac_ext_stream * hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) { struct hdac_bus *bus = sof_to_bus(sdev); + struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *stream = NULL; struct hdac_stream *s; @@ -163,8 +164,15 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) /* get an unused stream */ list_for_each_entry(s, &bus->stream_list, list) { if (s->direction == direction && !s->opened) { - s->opened = true; stream = stream_to_hdac_ext_stream(s); + hda_stream = container_of(stream, + struct sof_intel_hda_stream, + hda_stream); + /* check if the host DMA channel is reserved */ + if (hda_stream->host_reserved) + continue; + + s->opened = true; break; } } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 376b1ca51e2b..2862b4b3b07c 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -413,6 +413,7 @@ struct sof_intel_hda_stream { struct hdac_ext_stream hda_stream; struct sof_intel_stream stream; int hw_params_upon_resume; /* set up hw_params upon resume */ + int host_reserved; /* reserve host DMA channel */ }; #define hstream_to_sof_hda_stream(hstream) \ From 7077a07a72d38a78040873bbc13a77d1e45f8aa0 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:38 -0500 Subject: [PATCH 392/626] ASoC: SOF: Intel: hda: release link DMA for paused streams during suspend Paused streams do not get suspended when the system enters S3. So, clear and release link DMA channel for such streams in the hda_dsp_set_hw_params_upon_resume() callback. Also, invalidate the link DMA channel in the DAI config before restoring the dai config upon resume. Also, modify the signature for the set_hw_params_upon_resume() op to return an int. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 29 ++++++++++++++++++++++++++++- sound/soc/sof/intel/hda.h | 2 +- sound/soc/sof/ops.h | 5 +++-- sound/soc/sof/pm.c | 24 ++++++++++++++++++++---- sound/soc/sof/sof-priv.h | 2 +- 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 5b73115a0b78..c6eea3079ab7 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -454,18 +454,45 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state) return 0; } -void hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) +int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *stream; struct hdac_stream *s; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + struct snd_soc_pcm_runtime *rtd; + struct hdac_ext_link *link; + const char *name; + int stream_tag; +#endif + /* set internal flag for BE */ list_for_each_entry(s, &bus->stream_list, list) { stream = stream_to_hdac_ext_stream(s); hda_stream = container_of(stream, struct sof_intel_hda_stream, hda_stream); hda_stream->hw_params_upon_resume = 1; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* + * clear and release stream. This should already be taken care + * for running streams when the SUSPEND trigger is called. + * But paused streams do not get suspended, so this needs to be + * done explicitly during suspend. + */ + if (stream->link_substream) { + rtd = snd_pcm_substream_chip(stream->link_substream); + name = rtd->codec_dai->component->name; + link = snd_hdac_ext_bus_get_link(bus, name); + if (!link) + return -EINVAL; + stream_tag = hdac_stream(stream)->stream_tag; + snd_hdac_ext_link_clear_stream_id(link, stream_tag); + snd_hdac_ext_stream_release(stream, + HDAC_EXT_STREAM_TYPE_LINK); + } +#endif } + return 0; } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 2862b4b3b07c..327621ef5cf3 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -451,7 +451,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state); int hda_dsp_resume(struct snd_sof_dev *sdev); int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state); int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); -void hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); +int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags); void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); void hda_ipc_dump(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 80fc3b374c2b..a23297353750 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -134,10 +134,11 @@ static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev, return 0; } -static inline void snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev) +static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev) { if (sof_ops(sdev)->set_hw_params_upon_resume) - sof_ops(sdev)->set_hw_params_upon_resume(sdev); + return sof_ops(sdev)->set_hw_params_upon_resume(sdev); + return 0; } static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index b7843f02ef67..8eeb3a1029f2 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -153,6 +153,15 @@ static int sof_restore_pipelines(struct snd_sof_dev *sdev) continue; } + /* + * The link DMA channel would be invalidated for running + * streams but not for streams that were in the PAUSED + * state during suspend. So invalidate it here before setting + * the dai config in the DSP. + */ + if (config->type == SOF_DAI_INTEL_HDA) + config->hda.link_dma_ch = DMA_CHAN_INVALID; + ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, @@ -204,7 +213,7 @@ static int sof_send_pm_ipc(struct snd_sof_dev *sdev, int cmd) sizeof(pm_ctx), &reply, sizeof(reply)); } -static void sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) +static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) { struct snd_pcm_substream *substream; struct snd_sof_pcm *spcm; @@ -229,7 +238,7 @@ static void sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) } /* set internal flag for BE */ - snd_sof_dsp_hw_params_upon_resume(sdev); + return snd_sof_dsp_hw_params_upon_resume(sdev); } #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) @@ -333,8 +342,15 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) snd_sof_release_trace(sdev); /* set restore_stream for all streams during system suspend */ - if (!runtime_suspend) - sof_set_hw_params_upon_resume(sdev); + if (!runtime_suspend) { + ret = sof_set_hw_params_upon_resume(sdev); + if (ret < 0) { + dev_err(sdev->dev, + "error: setting hw_params flag during suspend %d\n", + ret); + return ret; + } + } #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) /* cache debugfs contents during runtime suspend */ diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index b80d93e5df2f..cf1b047f8cb6 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -172,7 +172,7 @@ struct snd_sof_dsp_ops { int (*runtime_suspend)(struct snd_sof_dev *sof_dev, int state); /* optional */ int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */ - void (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ + int (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ /* DSP clocking */ int (*set_clk)(struct snd_sof_dev *sof_dev, u32 freq); /* optional */ From 93146bc22f6131abf5161030f259e4b911d859eb Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:39 -0500 Subject: [PATCH 393/626] ASoC: SOF: Intel: hda: couple host and link DMA during FE hw_free Host and link DMA are decoupled during FE hw_params. So, they must be coupled in hw_free if the link DMA channel is idle. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 1 + sound/soc/sof/intel/cnl.c | 1 + sound/soc/sof/intel/hda-stream.c | 20 ++++++++++++++++++++ sound/soc/sof/intel/hda.h | 2 ++ sound/soc/sof/ops.h | 11 +++++++++++ sound/soc/sof/pcm.c | 7 +++++++ sound/soc/sof/sof-priv.h | 4 ++++ 7 files changed, 46 insertions(+) diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index f215d80dce2c..43d1c9f31ec4 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -61,6 +61,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .pcm_open = hda_dsp_pcm_open, .pcm_close = hda_dsp_pcm_close, .pcm_hw_params = hda_dsp_pcm_hw_params, + .pcm_hw_free = hda_dsp_stream_hw_free, .pcm_trigger = hda_dsp_pcm_trigger, .pcm_pointer = hda_dsp_pcm_pointer, diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index d59305787fc3..3840f81767fa 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -219,6 +219,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .pcm_open = hda_dsp_pcm_open, .pcm_close = hda_dsp_pcm_close, .pcm_hw_params = hda_dsp_pcm_hw_params, + .pcm_hw_free = hda_dsp_stream_hw_free, .pcm_trigger = hda_dsp_pcm_trigger, .pcm_pointer = hda_dsp_pcm_pointer, diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index a3f7c91469ec..ff6ab0c45d8e 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -438,6 +438,26 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, return ret; } +int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + struct hdac_stream *stream = substream->runtime->private_data; + struct hdac_ext_stream *link_dev = container_of(stream, + struct hdac_ext_stream, + hstream); + struct hdac_bus *bus = sof_to_bus(sdev); + u32 mask = 0x1 << stream->index; + + spin_lock(&bus->reg_lock); + /* couple host and link DMA if link DMA channel is idle */ + if (!link_dev->link_locked) + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, + SOF_HDA_REG_PP_PPCTL, mask, 0); + spin_unlock(&bus->reg_lock); + + return 0; +} + irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) { struct hdac_bus *bus = context; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 327621ef5cf3..8812dae9cf7a 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -468,6 +468,8 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct sof_ipc_stream_params *ipc_params); +int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream); int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, int cmd); snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index a23297353750..45a3d1091163 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -287,6 +287,17 @@ snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev, return 0; } +/* host stream hw free */ +static inline int +snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free) + return sof_ops(sdev)->pcm_hw_free(sdev, substream); + + return 0; +} + /* host stream trigger */ static inline int snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 6dc5f97be0bc..334e9d59b1ba 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -251,6 +251,13 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); + if (ret < 0) + return ret; + + ret = snd_sof_pcm_platform_hw_free(sdev, substream); + if (ret < 0) + dev_err(sdev->dev, "error: platform hw free failed\n"); + return ret; } diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index cf1b047f8cb6..58621db4fd31 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -143,6 +143,10 @@ struct snd_sof_dsp_ops { struct snd_pcm_hw_params *params, struct sof_ipc_stream_params *ipc_params); /* optional */ + /* host stream hw_free */ + int (*pcm_hw_free)(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream); /* optional */ + /* host stream trigger */ int (*pcm_trigger)(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, From 6297a0dc4c14a62bea5a9137ceef280cb7a80665 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:40 -0500 Subject: [PATCH 394/626] ASoC: SOF: Intel: hda: modify stream interrupt handler Modify the stream interrupt handler to always wake up the IRQ thread if the status register is valid. The IRQ thread performs the check for stream interrupts and RIRB interrupts in a loop to handle the case of missed interrupts when an unsolicited response from the codec is received just before the stream interrupt handler is completed. Signed-off-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 81 ++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index ff6ab0c45d8e..d44318040948 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -461,57 +461,40 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) { struct hdac_bus *bus = context; - struct sof_intel_hda_dev *sof_hda = bus_to_sof_hda(bus); - u32 stream_mask; + int ret = IRQ_WAKE_THREAD; u32 status; - if (!pm_runtime_active(bus->dev)) - return IRQ_NONE; - spin_lock(&bus->reg_lock); status = snd_hdac_chip_readl(bus, INTSTS); - stream_mask = GENMASK(sof_hda->stream_max - 1, 0) | AZX_INT_CTRL_EN; + dev_vdbg(bus->dev, "stream irq, INTSTS status: 0x%x\n", status); - /* Not stream interrupt or register inaccessible, ignore it.*/ - if (!(status & stream_mask) || status == 0xffffffff) { - spin_unlock(&bus->reg_lock); - return IRQ_NONE; - } - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - /* clear rirb int */ - status = snd_hdac_chip_readb(bus, RIRBSTS); - if (status & RIRB_INT_MASK) { - if (status & RIRB_INT_RESPONSE) - snd_hdac_bus_update_rirb(bus); - snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); - } -#endif + /* Register inaccessible, ignore it.*/ + if (status == 0xffffffff) + ret = IRQ_NONE; spin_unlock(&bus->reg_lock); - return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED; + return ret; } -irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) +static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) { - struct hdac_bus *bus = context; struct sof_intel_hda_dev *sof_hda = bus_to_sof_hda(bus); - u32 status = snd_hdac_chip_readl(bus, INTSTS); struct hdac_stream *s; + bool active = false; u32 sd_status; - /* check streams */ list_for_each_entry(s, &bus->stream_list, list) { - if (status & (1 << s->index) && s->opened) { + if (status & BIT(s->index) && s->opened) { sd_status = snd_hdac_stream_readb(s, SD_STS); dev_vdbg(bus->dev, "stream %d status 0x%x\n", s->index, sd_status); - snd_hdac_stream_writeb(s, SD_STS, SD_INT_MASK); + snd_hdac_stream_writeb(s, SD_STS, sd_status); + active = true; if (!s->substream || !s->running || (sd_status & SOF_HDA_CL_DMA_SD_INT_COMPLETE) == 0) @@ -520,10 +503,50 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) /* Inform ALSA only in case not do that with IPC */ if (sof_hda->no_ipc_position) snd_sof_pcm_period_elapsed(s->substream); - } } + return active; +} + +irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) +{ + struct hdac_bus *bus = context; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + u32 rirb_status; +#endif + bool active; + u32 status; + int i; + + /* + * Loop 10 times to handle missed interrupts caused by + * unsolicited responses from the codec + */ + for (i = 0, active = true; i < 10 && active; i++) { + spin_lock_irq(&bus->reg_lock); + + status = snd_hdac_chip_readl(bus, INTSTS); + + /* check streams */ + active = hda_dsp_stream_check(bus, status); + + /* check and clear RIRB interrupt */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + if (status & AZX_INT_CTRL_EN) { + rirb_status = snd_hdac_chip_readb(bus, RIRBSTS); + if (rirb_status & RIRB_INT_MASK) { + active = true; + if (rirb_status & RIRB_INT_RESPONSE) + snd_hdac_bus_update_rirb(bus); + snd_hdac_chip_writeb(bus, RIRBSTS, + RIRB_INT_MASK); + } + } +#endif + spin_unlock_irq(&bus->reg_lock); + } + return IRQ_HANDLED; } From 7fd572e7d317fa51049d623badb8b2874bfd0119 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 12 Jun 2019 12:23:41 -0500 Subject: [PATCH 395/626] ASoC: SOF: Intel: hda-stream: fix a deadlock with bus->reg_lock We should use irq disabled mode when read/write hda registers from thread context, as we need to hold the same bus->reg_lock in interrupt context hda_dsp_stream_interrupt(), otherwise, when we are holding the lock in hda_dsp_stream_hw_free() and the interrupt arrives, we will get deadlock in the interrupt handler. Error logs like this: [ 5.603606] CPU0 [ 5.603606] ---- [ 5.603607] lock(&(&bus->reg_lock)->rlock); [ 5.603608] [ 5.603609] lock(&(&bus->reg_lock)->rlock); [ 5.603610] *** DEADLOCK *** [ 5.603611] 2 locks held by pulseaudio/2329: [ 5.603612] #0: 000000005fcf26c6 (&card->mutex/1){+.+.}, at: dpcm_fe_dai_hw_free+0x2b/0x110 [snd_soc_core] [ 5.603619] #1: 00000000ef369faf (&rtd->pcm_mutex){+.+.}, at: soc_pcm_hw_free+0x2e/0x1c0 [snd_soc_core] The fix is simple, let's switch to use spin_lock/unlock_irq(). Reported-by: Xun Zhang Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index d44318040948..23cff5aca007 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -448,12 +448,12 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, struct hdac_bus *bus = sof_to_bus(sdev); u32 mask = 0x1 << stream->index; - spin_lock(&bus->reg_lock); + spin_lock_irq(&bus->reg_lock); /* couple host and link DMA if link DMA channel is idle */ if (!link_dev->link_locked) snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, mask, 0); - spin_unlock(&bus->reg_lock); + spin_unlock_irq(&bus->reg_lock); return 0; } From 24b6ff686fce808346c129bce52836c3339733bf Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Wed, 12 Jun 2019 12:23:42 -0500 Subject: [PATCH 396/626] ASoC: SOF: Intel: hda: use the SOF defined ppcap functions Unify ppcap function setup by using SOF common functions for both HDA and non-HDA cases. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index c6eea3079ab7..883134d535b3 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -307,18 +307,14 @@ static int hda_suspend(struct snd_sof_dev *sdev, int state) return ret; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - /* disable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_int_enable(bus, false); - snd_hdac_ext_bus_ppcap_enable(bus, false); - - /* disable hda bus irq and i/o */ - snd_hdac_bus_stop_chip(bus); -#else /* disable ppcap interrupt */ hda_dsp_ctrl_ppcap_enable(sdev, false); hda_dsp_ctrl_ppcap_int_enable(sdev, false); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* disable hda bus irq and i/o */ + snd_hdac_bus_stop_chip(bus); +#else /* disable hda bus irq */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, @@ -370,10 +366,6 @@ static int hda_resume(struct snd_sof_dev *sdev) bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); hda_dsp_ctrl_misc_clock_gating(sdev, true); - - /* enable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_enable(bus, true); - snd_hdac_ext_bus_ppcap_int_enable(bus, true); #else hda_dsp_ctrl_misc_clock_gating(sdev, false); @@ -400,11 +392,11 @@ static int hda_resume(struct snd_sof_dev *sdev) SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); hda_dsp_ctrl_misc_clock_gating(sdev, true); +#endif /* enable ppcap interrupt */ hda_dsp_ctrl_ppcap_enable(sdev, true); hda_dsp_ctrl_ppcap_int_enable(sdev, true); -#endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* turn off the links that were off before suspend */ From 13063a2ccf79d232889491105a7bd9d552e417fc Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Wed, 12 Jun 2019 12:23:43 -0500 Subject: [PATCH 397/626] ASoC: SOF: Intel: hda: add function for hda stop chip Add common hda_dsp_ctrl_stop_chip() function to stop controller with the same function handling both HDA and non-HDA cases. This function disables IRQs and clears status masks. When CONFIG_SND_SOC_SOF_HDA is defined, also disables the CORB/RIRB, and stops i/o. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 67 ++++++++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 2 +- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 07bc123112c9..688ab8d895a9 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -263,3 +263,70 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) return ret; } + +void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_stream *stream; + int sd_offset; + + if (!bus->chip_init) + return; + + /* disable interrupts in stream descriptor */ + list_for_each_entry(stream, &bus->stream_list, list) { + sd_offset = SOF_STREAM_SD_OFFSET(stream); + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + sd_offset + + SOF_HDA_ADSP_REG_CL_SD_CTL, + SOF_HDA_CL_DMA_SD_INT_MASK, + 0); + } + + /* disable SIE for all streams */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, + SOF_HDA_INT_ALL_STREAM, 0); + + /* disable controller CIE and GIE */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, + 0); + + /* clear stream status */ + list_for_each_entry(stream, &bus->stream_list, list) { + sd_offset = SOF_STREAM_SD_OFFSET(stream); + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + sd_offset + + SOF_HDA_ADSP_REG_CL_SD_STS, + SOF_HDA_CL_DMA_SD_INT_MASK, + SOF_HDA_CL_DMA_SD_INT_MASK); + } + + /* clear WAKESTS */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, + SOF_HDA_WAKESTS_INT_MASK, + SOF_HDA_WAKESTS_INT_MASK); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* clear rirb status */ + snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); +#endif + + /* clear interrupt status register */ + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* disable CORB/RIRB */ + snd_hdac_bus_stop_cmd_io(bus); +#endif + /* disable position buffer */ + if (bus->posbuf.addr) { + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_ADSP_DPLBASE, 0); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_ADSP_DPUBASE, 0); + } + + bus->chip_init = false; +} diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 8812dae9cf7a..50653859e0a0 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -538,7 +538,7 @@ int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev, bool reset); void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable); int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable); int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset); - +void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev); /* * HDA bus operations. */ From 9a50ee58b8b11300788d41cd1c0f370833424823 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Wed, 12 Jun 2019 12:23:44 -0500 Subject: [PATCH 398/626] ASoC: SOF: Intel: hda: use the defined stop chip in suspend Unify suspend code by using SOF common function hda_dsp_ctrl_stop_chip() which can handle both HDA and non-HDA cases. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 883134d535b3..f2c5a12db930 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -311,15 +311,8 @@ static int hda_suspend(struct snd_sof_dev *sdev, int state) hda_dsp_ctrl_ppcap_enable(sdev, false); hda_dsp_ctrl_ppcap_int_enable(sdev, false); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - /* disable hda bus irq and i/o */ - snd_hdac_bus_stop_chip(bus); -#else - /* disable hda bus irq */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, - 0); -#endif + /* disable hda bus irq and streams */ + hda_dsp_ctrl_stop_chip(sdev); /* disable LP retention mode */ snd_sof_pci_update_bits(sdev, PCI_PGCTL, From 3a39e0eae80919a15831f66324d4530454b4f495 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 12 Jun 2019 12:23:45 -0500 Subject: [PATCH 399/626] ASoC: SOF: Intel: hda: clear stream status and wakests properly Stream status and WAKESTS registers need to be cleared by writing to them with snd_sof_dsp_write(). snd_sof_dsp_update_bits() only writes if the value is changed and will result in not clearing the status. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 688ab8d895a9..ea63f83a509b 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -217,17 +217,14 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) /* clear stream status */ list_for_each_entry(stream, &bus->stream_list, list) { sd_offset = SOF_STREAM_SD_OFFSET(stream); - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS, - SOF_HDA_CL_DMA_SD_INT_MASK, - SOF_HDA_CL_DMA_SD_INT_MASK); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, + sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, + SOF_HDA_CL_DMA_SD_INT_MASK); } /* clear WAKESTS */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, - SOF_HDA_WAKESTS_INT_MASK, - SOF_HDA_WAKESTS_INT_MASK); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, + SOF_HDA_WAKESTS_INT_MASK); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* clear rirb status */ @@ -295,17 +292,14 @@ void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) /* clear stream status */ list_for_each_entry(stream, &bus->stream_list, list) { sd_offset = SOF_STREAM_SD_OFFSET(stream); - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS, - SOF_HDA_CL_DMA_SD_INT_MASK, - SOF_HDA_CL_DMA_SD_INT_MASK); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, + sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, + SOF_HDA_CL_DMA_SD_INT_MASK); } /* clear WAKESTS */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, - SOF_HDA_WAKESTS_INT_MASK, - SOF_HDA_WAKESTS_INT_MASK); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, + SOF_HDA_WAKESTS_INT_MASK); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* clear rirb status */ From 7bcaf0f2cdfacca2226eee8895f64bc019d5a8be Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Wed, 12 Jun 2019 12:23:46 -0500 Subject: [PATCH 400/626] ASoC: SOF: Intel: hda: make sure DMA is start/stop by read the RUN bit As per the HW recommendation, after setting the RUN bit (start as 1, stop as 0), software must read the bit back to make sure the bit is set right, before modifying related control registers/re-starting the DMA engine. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 22 ++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 6 ++++++ 2 files changed, 28 insertions(+) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 23cff5aca007..13d114993f96 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -217,6 +217,9 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, { struct hdac_stream *hstream = &stream->hstream; int sd_offset = SOF_STREAM_SD_OFFSET(hstream); + u32 dma_start = SOF_HDA_SD_CTL_DMA_START; + int ret; + u32 run; /* cmd must be for audio stream */ switch (cmd) { @@ -234,6 +237,16 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, SOF_HDA_SD_CTL_DMA_START | SOF_HDA_CL_DMA_SD_INT_MASK); + ret = snd_sof_dsp_read_poll_timeout(sdev, + HDA_DSP_HDA_BAR, + sd_offset, run, + ((run & dma_start) == dma_start), + HDA_DSP_REG_POLL_INTERVAL_US, + HDA_DSP_STREAM_RUN_TIMEOUT); + + if (ret) + return ret; + hstream->running = true; break; case SNDRV_PCM_TRIGGER_SUSPEND: @@ -244,6 +257,15 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, SOF_HDA_SD_CTL_DMA_START | SOF_HDA_CL_DMA_SD_INT_MASK, 0x0); + ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_HDA_BAR, + sd_offset, run, + !(run & dma_start), + HDA_DSP_REG_POLL_INTERVAL_US, + HDA_DSP_STREAM_RUN_TIMEOUT); + + if (ret) + return ret; + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, SOF_HDA_CL_DMA_SD_INT_MASK); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 50653859e0a0..73d7cc08afc2 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -159,6 +159,12 @@ #define HDA_DSP_MBOX_UPLINK_OFFSET 0x81000 #define HDA_DSP_STREAM_RESET_TIMEOUT 300 +/* + * Timeout in us, for setting the stream RUN bit, during + * start/stop the stream. The timeout expires if new RUN bit + * value cannot be read back within the specified time. + */ +#define HDA_DSP_STREAM_RUN_TIMEOUT 300 #define HDA_DSP_CL_TRIGGER_TIMEOUT 300 #define HDA_DSP_SPIB_ENABLE 1 From 5b8cc7d17f56257056ed65624dec28dcdf14e87e Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Wed, 12 Jun 2019 12:23:47 -0500 Subject: [PATCH 401/626] ASoC: SOF: Intel: hda: make sure RUN bit setting to 0 during clear stream status Before clearing stream statuses, ensure RUN bit update has taken effect by reading the value back. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 13d114993f96..ad8d41f22e92 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -295,7 +295,9 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, struct hdac_stream *hstream = &stream->hstream; int sd_offset = SOF_STREAM_SD_OFFSET(hstream); int ret, timeout = HDA_DSP_STREAM_RESET_TIMEOUT; + u32 dma_start = SOF_HDA_SD_CTL_DMA_START; u32 val, mask; + u32 run; if (!stream) { dev_err(sdev->dev, "error: no stream available\n"); @@ -316,6 +318,16 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, SOF_HDA_CL_DMA_SD_INT_MASK | SOF_HDA_SD_CTL_DMA_START, 0); + + ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_HDA_BAR, + sd_offset, run, + !(run & dma_start), + HDA_DSP_REG_POLL_INTERVAL_US, + HDA_DSP_STREAM_RUN_TIMEOUT); + + if (ret) + return ret; + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, SOF_HDA_CL_DMA_SD_INT_MASK, @@ -368,6 +380,16 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, SOF_HDA_CL_DMA_SD_INT_MASK | SOF_HDA_SD_CTL_DMA_START, 0); + + ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_HDA_BAR, + sd_offset, run, + !(run & dma_start), + HDA_DSP_REG_POLL_INTERVAL_US, + HDA_DSP_STREAM_RUN_TIMEOUT); + + if (ret) + return ret; + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, SOF_HDA_CL_DMA_SD_INT_MASK, From 9de7eaddfa7f47fbb1cd9cdb9aab405599ef414e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 17 Jun 2019 14:45:49 +0200 Subject: [PATCH 402/626] ASoC: SOF: disallow building without CONFIG_PCI again Compile-testing without PCI just causes warnings: sound/soc/sof/sof-pci-dev.c:330:13: error: 'sof_pci_remove' defined but not used [-Werror=unused-function] static void sof_pci_remove(struct pci_dev *pci) ^~~~~~~~~~~~~~ sound/soc/sof/sof-pci-dev.c:230:12: error: 'sof_pci_probe' defined but not used [-Werror=unused-function] static int sof_pci_probe(struct pci_dev *pci, ^~~~~~~~~~~~~ I tried to fix this in a way that would still allow compile tests, but it got too ugly, so this just reverts the patch that allowed it in the first place. Most architectures do allow enabling PCI, so the value of the COMPILE_TEST alternative was not very high to start with. Fixes: e13ef82a9ab8 ("ASoC: SOF: add COMPILE_TEST for PCI options") Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 2 +- sound/soc/sof/intel/hda.c | 13 ++----------- sound/soc/sof/sof-pci-dev.c | 4 ---- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 1d4b4dced4b6..bc6d7b311af4 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -10,7 +10,7 @@ if SND_SOC_SOF_TOPLEVEL config SND_SOC_SOF_PCI tristate "SOF PCI enumeration support" - depends on PCI || COMPILE_TEST + depends on PCI select SND_SOC_SOF select SND_SOC_ACPI if ACPI select SND_SOC_SOF_OPTIONS diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index af546e42e1d9..8754dfe75000 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -525,9 +525,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * TODO: support interrupt mode selection with kernel parameter * support msi multiple vectors */ -#if IS_ENABLED(CONFIG_PCI) ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI); -#endif if (ret < 0) { dev_info(sdev->dev, "use legacy interrupt mode\n"); /* @@ -539,9 +537,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->msi_enabled = 0; } else { dev_info(sdev->dev, "use msi interrupt mode\n"); -#if IS_ENABLED(CONFIG_PCI) hdev->irq = pci_irq_vector(pci, 0); -#endif /* ipc irq number is the same of hda irq */ sdev->ipc_irq = hdev->irq; sdev->msi_enabled = 1; @@ -598,10 +594,8 @@ free_ipc_irq: free_hda_irq: free_irq(hdev->irq, bus); free_irq_vector: -#if IS_ENABLED(CONFIG_PCI) if (sdev->msi_enabled) pci_free_irq_vectors(pci); -#endif free_streams: hda_dsp_stream_free(sdev); /* dsp_unmap: not currently used */ @@ -616,6 +610,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); + struct pci_dev *pci = to_pci_dev(sdev->dev); const struct sof_intel_dsp_desc *chip = hda->desc; #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) @@ -644,12 +639,8 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) free_irq(sdev->ipc_irq, sdev); free_irq(hda->irq, bus); -#if IS_ENABLED(CONFIG_PCI) - if (sdev->msi_enabled) { - struct pci_dev *pci = to_pci_dev(sdev->dev); + if (sdev->msi_enabled) pci_free_irq_vectors(pci); - } -#endif hda_dsp_stream_free(sdev); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index ab58d4f9119f..e2b19782f01a 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -251,11 +251,9 @@ static int sof_pci_probe(struct pci_dev *pci, if (!sof_pdata) return -ENOMEM; -#if IS_ENABLED(CONFIG_PCI) ret = pcim_enable_device(pci); if (ret < 0) return ret; -#endif ret = pci_request_regions(pci, "Audio DSP"); if (ret < 0) @@ -388,7 +386,6 @@ static const struct pci_device_id sof_pci_ids[] = { }; MODULE_DEVICE_TABLE(pci, sof_pci_ids); -#if IS_ENABLED(CONFIG_PCI) /* pci_driver definition */ static struct pci_driver snd_sof_pci_driver = { .name = "sof-audio-pci", @@ -400,6 +397,5 @@ static struct pci_driver snd_sof_pci_driver = { }, }; module_pci_driver(snd_sof_pci_driver); -#endif MODULE_LICENSE("Dual BSD/GPL"); From 8893cba2fa6994ac8434cbc616eeddcde211ec45 Mon Sep 17 00:00:00 2001 From: Fletcher Woodruff Date: Fri, 14 Jun 2019 13:48:51 -0600 Subject: [PATCH 403/626] ASoC: rt5677: fall back to DT prop names on error The rt5677 driver uses ACPI-style property names to read from the device API. However, these do not match the property names in _DSD used on the Chromebook Pixel 2015, which are closer to the Device Tree style. Unify the two functions for reading from the device API so that they try ACPI-style names first and fall back to the DT names on error. With this patch, plugging and unplugging the headphone jack switches between headphones and speakers automatically. Signed-off-by: Fletcher Woodruff Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index c49b5c218666..fe000f30b9ad 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5020,48 +5020,50 @@ static const struct acpi_device_id rt5677_acpi_match[] = { }; MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match); -static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, +static void rt5677_read_device_properties(struct rt5677_priv *rt5677, struct device *dev) { u32 val; - if (!device_property_read_u32(dev, "DCLK", &val)) - rt5677->pdata.dmic2_clk_pin = val; + rt5677->pdata.in1_diff = + device_property_read_bool(dev, "IN1") || + device_property_read_bool(dev, "realtek,in1-differential"); - rt5677->pdata.in1_diff = device_property_read_bool(dev, "IN1"); - rt5677->pdata.in2_diff = device_property_read_bool(dev, "IN2"); - rt5677->pdata.lout1_diff = device_property_read_bool(dev, "OUT1"); - rt5677->pdata.lout2_diff = device_property_read_bool(dev, "OUT2"); - rt5677->pdata.lout3_diff = device_property_read_bool(dev, "OUT3"); + rt5677->pdata.in2_diff = + device_property_read_bool(dev, "IN2") || + device_property_read_bool(dev, "realtek,in2-differential"); - device_property_read_u32(dev, "JD1", &rt5677->pdata.jd1_gpio); - device_property_read_u32(dev, "JD2", &rt5677->pdata.jd2_gpio); - device_property_read_u32(dev, "JD3", &rt5677->pdata.jd3_gpio); -} + rt5677->pdata.lout1_diff = + device_property_read_bool(dev, "OUT1") || + device_property_read_bool(dev, "realtek,lout1-differential"); -static void rt5677_read_device_properties(struct rt5677_priv *rt5677, - struct device *dev) -{ - rt5677->pdata.in1_diff = device_property_read_bool(dev, - "realtek,in1-differential"); - rt5677->pdata.in2_diff = device_property_read_bool(dev, - "realtek,in2-differential"); - rt5677->pdata.lout1_diff = device_property_read_bool(dev, - "realtek,lout1-differential"); - rt5677->pdata.lout2_diff = device_property_read_bool(dev, - "realtek,lout2-differential"); - rt5677->pdata.lout3_diff = device_property_read_bool(dev, - "realtek,lout3-differential"); + rt5677->pdata.lout2_diff = + device_property_read_bool(dev, "OUT2") || + device_property_read_bool(dev, "realtek,lout2-differential"); + + rt5677->pdata.lout3_diff = + device_property_read_bool(dev, "OUT3") || + device_property_read_bool(dev, "realtek,lout3-differential"); device_property_read_u8_array(dev, "realtek,gpio-config", - rt5677->pdata.gpio_config, RT5677_GPIO_NUM); + rt5677->pdata.gpio_config, + RT5677_GPIO_NUM); - device_property_read_u32(dev, "realtek,jd1-gpio", - &rt5677->pdata.jd1_gpio); - device_property_read_u32(dev, "realtek,jd2-gpio", - &rt5677->pdata.jd2_gpio); - device_property_read_u32(dev, "realtek,jd3-gpio", - &rt5677->pdata.jd3_gpio); + if (!device_property_read_u32(dev, "DCLK", &val) || + !device_property_read_u32(dev, "realtek,dmic2_clk_pin", &val)) + rt5677->pdata.dmic2_clk_pin = val; + + if (!device_property_read_u32(dev, "JD1", &val) || + !device_property_read_u32(dev, "realtek,jd1-gpio", &val)) + rt5677->pdata.jd1_gpio = val; + + if (!device_property_read_u32(dev, "JD2", &val) || + !device_property_read_u32(dev, "realtek,jd2-gpio", &val)) + rt5677->pdata.jd2_gpio = val; + + if (!device_property_read_u32(dev, "JD3", &val) || + !device_property_read_u32(dev, "realtek,jd3-gpio", &val)) + rt5677->pdata.jd3_gpio = val; } static struct regmap_irq rt5677_irqs[] = { @@ -5144,20 +5146,18 @@ static int rt5677_i2c_probe(struct i2c_client *i2c) match_id = of_match_device(rt5677_of_match, &i2c->dev); if (match_id) rt5677->type = (enum rt5677_type)match_id->data; - - rt5677_read_device_properties(rt5677, &i2c->dev); } else if (ACPI_HANDLE(&i2c->dev)) { const struct acpi_device_id *acpi_id; acpi_id = acpi_match_device(rt5677_acpi_match, &i2c->dev); if (acpi_id) rt5677->type = (enum rt5677_type)acpi_id->driver_data; - - rt5677_read_acpi_properties(rt5677, &i2c->dev); } else { return -EINVAL; } + rt5677_read_device_properties(rt5677, &i2c->dev); + /* pow-ldo2 and reset are optional. The codec pins may be statically * connected on the board without gpios. If the gpio device property * isn't specified, devm_gpiod_get_optional returns NULL. From 241800642ea3482ab3f80a2a3662e9f2e6a82208 Mon Sep 17 00:00:00 2001 From: Fletcher Woodruff Date: Fri, 14 Jun 2019 13:48:52 -0600 Subject: [PATCH 404/626] ASoC: rt5677: move jack-detect init to i2c probe This patch moves the code to select the gpios for jack detection from rt5677_probe to rt5677_init_irq (called from rt5677_i2c_probe). It also sets some registers to fix bugs related to jack detection, and adds some constants and comments to make it easier to understand what certain register settings are controlling. Signed-off-by: Ben Zhang Signed-off-by: Fletcher Woodruff Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 60 ++++++++++++++++++++++----------------- sound/soc/codecs/rt5677.h | 6 ++++ 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index fe000f30b9ad..87a92ba0d040 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4716,37 +4716,13 @@ static int rt5677_probe(struct snd_soc_component *component) snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF); - regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); + regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, + ~RT5677_IRQ_DEBOUNCE_SEL_MASK, 0x0020); regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00); for (i = 0; i < RT5677_GPIO_NUM; i++) rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]); - if (rt5677->irq_data) { - regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL1, 0x8000, - 0x8000); - regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x0018, - 0x0008); - - if (rt5677->pdata.jd1_gpio) - regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, - RT5677_SEL_GPIO_JD1_MASK, - rt5677->pdata.jd1_gpio << - RT5677_SEL_GPIO_JD1_SFT); - - if (rt5677->pdata.jd2_gpio) - regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, - RT5677_SEL_GPIO_JD2_MASK, - rt5677->pdata.jd2_gpio << - RT5677_SEL_GPIO_JD2_SFT); - - if (rt5677->pdata.jd3_gpio) - regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, - RT5677_SEL_GPIO_JD3_MASK, - rt5677->pdata.jd3_gpio << - RT5677_SEL_GPIO_JD3_SFT); - } - mutex_init(&rt5677->dsp_cmd_lock); mutex_init(&rt5677->dsp_pri_lock); @@ -5096,6 +5072,7 @@ static int rt5677_init_irq(struct i2c_client *i2c) { int ret; struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c); + unsigned int jd_mask = 0, jd_val = 0; if (!rt5677->pdata.jd1_gpio && !rt5677->pdata.jd2_gpio && @@ -5107,6 +5084,37 @@ static int rt5677_init_irq(struct i2c_client *i2c) return -EINVAL; } + /* + * Select RC as the debounce clock so that GPIO works even when + * MCLK is gated which happens when there is no audio stream + * (SND_SOC_BIAS_OFF). + */ + regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, + RT5677_IRQ_DEBOUNCE_SEL_MASK, + RT5677_IRQ_DEBOUNCE_SEL_RC); + + /* Enable auto power on RC when GPIO states are changed */ + regmap_update_bits(rt5677->regmap, RT5677_GEN_CTRL1, 0xff, 0xff); + + /* Select and enable jack detection sources per platform data */ + if (rt5677->pdata.jd1_gpio) { + jd_mask |= RT5677_SEL_GPIO_JD1_MASK; + jd_val |= rt5677->pdata.jd1_gpio << RT5677_SEL_GPIO_JD1_SFT; + } + if (rt5677->pdata.jd2_gpio) { + jd_mask |= RT5677_SEL_GPIO_JD2_MASK; + jd_val |= rt5677->pdata.jd2_gpio << RT5677_SEL_GPIO_JD2_SFT; + } + if (rt5677->pdata.jd3_gpio) { + jd_mask |= RT5677_SEL_GPIO_JD3_MASK; + jd_val |= rt5677->pdata.jd3_gpio << RT5677_SEL_GPIO_JD3_SFT; + } + regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, jd_mask, jd_val); + + /* Set GPIO1 pin to be IRQ output */ + regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL1, + RT5677_GPIO1_PIN_MASK, RT5677_GPIO1_PIN_IRQ); + ret = regmap_add_irq_chip(rt5677->regmap, i2c->irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0, &rt5677_irq_chip, &rt5677->irq_data); diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 076e5161d8da..c26edd387e34 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h @@ -1664,6 +1664,12 @@ #define RT5677_GPIO6_P_NOR (0x0 << 0) #define RT5677_GPIO6_P_INV (0x1 << 0) +/* General Control (0xfa) */ +#define RT5677_IRQ_DEBOUNCE_SEL_MASK (0x3 << 3) +#define RT5677_IRQ_DEBOUNCE_SEL_MCLK (0x0 << 3) +#define RT5677_IRQ_DEBOUNCE_SEL_RC (0x1 << 3) +#define RT5677_IRQ_DEBOUNCE_SEL_SLIM (0x2 << 3) + /* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */ #define RT5677_DSP_IB_01_H (0x1 << 15) #define RT5677_DSP_IB_01_H_SFT 15 From 3e802e90ffcce333127d928eaefdfcc34af233e8 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Sun, 2 Jun 2019 16:55:49 +0200 Subject: [PATCH 405/626] ASoC: ti: Fix SDMA users not providing channel names McBSP used to work correctly as long as compat DMA probing, removed by commit 642aafea8889 ("ASoC: ti: remove compat dma probing"), was available. New method of DMA probing apparently requires users to provide channel names when registering with SDMA, while McBSP passes NULLs. Fix it. The same probably applies to McASP (not tested), hence the patch fixes both. Fixes: 642aafea8889 ("ASoC: ti: remove compat dma probing") Signed-off-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 2 +- sound/soc/ti/omap-mcbsp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 9fbc759fdefe..f31805920e3e 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -2237,7 +2237,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) ret = edma_pcm_platform_register(&pdev->dev); break; case PCM_SDMA: - ret = sdma_pcm_platform_register(&pdev->dev, NULL, NULL); + ret = sdma_pcm_platform_register(&pdev->dev, "tx", "rx"); break; default: dev_err(&pdev->dev, "No DMA controller found (%d)\n", ret); diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index a395598f1f20..610c5e706fd2 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -1438,7 +1438,7 @@ static int asoc_mcbsp_probe(struct platform_device *pdev) if (ret) return ret; - return sdma_pcm_platform_register(&pdev->dev, NULL, NULL); + return sdma_pcm_platform_register(&pdev->dev, "tx", "rx"); } static int asoc_mcbsp_remove(struct platform_device *pdev) From 501e94b52aeda5841a60ceead5984ff575aeefa0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 17 Jun 2019 16:40:48 +0200 Subject: [PATCH 406/626] ASoC: Add missing newline at end of file "git diff" says: \ No newline at end of file after modifying the files. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- sound/soc/mediatek/common/Makefile | 2 +- sound/soc/tegra/Makefile | 2 +- sound/usb/bcd2000/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/common/Makefile b/sound/soc/mediatek/common/Makefile index 9ab90433a8d7..acbe01e9e928 100644 --- a/sound/soc/mediatek/common/Makefile +++ b/sound/soc/mediatek/common/Makefile @@ -3,4 +3,4 @@ snd-soc-mtk-common-objs := mtk-afe-platform-driver.o mtk-afe-fe-dai.o obj-$(CONFIG_SND_SOC_MEDIATEK) += snd-soc-mtk-common.o -obj-$(CONFIG_SND_SOC_MTK_BTCVSD) += mtk-btcvsd.o \ No newline at end of file +obj-$(CONFIG_SND_SOC_MTK_BTCVSD) += mtk-btcvsd.o diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index 2329b72c93e3..c84f183919f2 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -37,4 +37,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o -obj-$(CONFIG_SND_SOC_TEGRA_SGTL5000) += snd-soc-tegra-sgtl5000.o \ No newline at end of file +obj-$(CONFIG_SND_SOC_TEGRA_SGTL5000) += snd-soc-tegra-sgtl5000.o diff --git a/sound/usb/bcd2000/Makefile b/sound/usb/bcd2000/Makefile index f09ccc0af6ff..0a100310a671 100644 --- a/sound/usb/bcd2000/Makefile +++ b/sound/usb/bcd2000/Makefile @@ -1,3 +1,3 @@ snd-bcd2000-y := bcd2000.o -obj-$(CONFIG_SND_BCD2000) += snd-bcd2000.o \ No newline at end of file +obj-$(CONFIG_SND_BCD2000) += snd-bcd2000.o From 18f26034be2711254adfa8923dfd263b50d4018a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:01 +0900 Subject: [PATCH 407/626] ALSA: firewire-motu: unify the count of subscriber for packet streaming Two counters are used to maintain isochronous packet streaming for both directions. However, like the other drivers, they can be replaced with one counter. This commit unifies them. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-midi.c | 8 ++++---- sound/firewire/motu/motu-pcm.c | 8 ++++---- sound/firewire/motu/motu-stream.c | 17 ++++++----------- sound/firewire/motu/motu.h | 3 +-- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/sound/firewire/motu/motu-midi.c b/sound/firewire/motu/motu-midi.c index e55cab6d79c7..b2d339a8ef3f 100644 --- a/sound/firewire/motu/motu-midi.c +++ b/sound/firewire/motu/motu-midi.c @@ -18,7 +18,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) mutex_lock(&motu->mutex); - motu->capture_substreams++; + motu->substreams_counter++; err = snd_motu_stream_start_duplex(motu, 0); mutex_unlock(&motu->mutex); @@ -40,7 +40,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) mutex_lock(&motu->mutex); - motu->playback_substreams++; + motu->substreams_counter++; err = snd_motu_stream_start_duplex(motu, 0); mutex_unlock(&motu->mutex); @@ -57,7 +57,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) mutex_lock(&motu->mutex); - motu->capture_substreams--; + motu->substreams_counter--; snd_motu_stream_stop_duplex(motu); mutex_unlock(&motu->mutex); @@ -72,7 +72,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) mutex_lock(&motu->mutex); - motu->playback_substreams--; + motu->substreams_counter--; snd_motu_stream_stop_duplex(motu); mutex_unlock(&motu->mutex); diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index ab69d7e6ac05..b0e5ebf05bec 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -203,7 +203,7 @@ static int capture_hw_params(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&motu->mutex); - motu->capture_substreams++; + motu->substreams_counter++; mutex_unlock(&motu->mutex); } @@ -222,7 +222,7 @@ static int playback_hw_params(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&motu->mutex); - motu->playback_substreams++; + motu->substreams_counter++; mutex_unlock(&motu->mutex); } @@ -236,7 +236,7 @@ static int capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&motu->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - motu->capture_substreams--; + motu->substreams_counter--; snd_motu_stream_stop_duplex(motu); @@ -252,7 +252,7 @@ static int playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&motu->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - motu->playback_substreams--; + motu->substreams_counter--; snd_motu_stream_stop_duplex(motu); diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 73e7a5e527fc..c136d7f8c49c 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -207,7 +207,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) unsigned int curr_rate; int err = 0; - if (motu->capture_substreams == 0 && motu->playback_substreams == 0) + if (motu->substreams_counter == 0) return 0; /* Some packet queueing errors. */ @@ -271,8 +271,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) } } - if (!amdtp_stream_running(&motu->tx_stream) && - motu->capture_substreams > 0) { + if (!amdtp_stream_running(&motu->tx_stream)) { err = start_isoc_ctx(motu, &motu->tx_stream); if (err < 0) { dev_err(&motu->unit->device, @@ -291,15 +290,12 @@ stop_streams: void snd_motu_stream_stop_duplex(struct snd_motu *motu) { - if (motu->capture_substreams == 0) { + if (motu->substreams_counter == 0) { if (amdtp_stream_running(&motu->tx_stream)) stop_isoc_ctx(motu, &motu->tx_stream); - if (motu->playback_substreams == 0) { - if (amdtp_stream_running(&motu->rx_stream)) - stop_isoc_ctx(motu, &motu->rx_stream); - stop_both_streams(motu); - } + if (amdtp_stream_running(&motu->rx_stream)) + stop_isoc_ctx(motu, &motu->rx_stream); } } @@ -372,8 +368,7 @@ void snd_motu_stream_destroy_duplex(struct snd_motu *motu) destroy_stream(motu, AMDTP_IN_STREAM); destroy_stream(motu, AMDTP_OUT_STREAM); - motu->playback_substreams = 0; - motu->capture_substreams = 0; + motu->substreams_counter = 0; } static void motu_lock_changed(struct snd_motu *motu) diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 1cd112be7dad..ae4b37cdfade 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -60,8 +60,7 @@ struct snd_motu { struct amdtp_stream rx_stream; struct fw_iso_resources tx_resources; struct fw_iso_resources rx_resources; - unsigned int capture_substreams; - unsigned int playback_substreams; + unsigned int substreams_counter; /* For notification. */ struct fw_address_handler async_handler; From f6341db65a0ad73e0eed10db424958919ce13dc2 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:02 +0900 Subject: [PATCH 408/626] ALSA: firewire-motu: unify midi callback function Two sets of callbacks for rawmidi.open/close but they have the same codes. This commit unifies each of the callbacks. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-midi.c | 49 ++++----------------------------- 1 file changed, 6 insertions(+), 43 deletions(-) diff --git a/sound/firewire/motu/motu-midi.c b/sound/firewire/motu/motu-midi.c index b2d339a8ef3f..3b205386ed24 100644 --- a/sound/firewire/motu/motu-midi.c +++ b/sound/firewire/motu/motu-midi.c @@ -7,7 +7,7 @@ */ #include "motu.h" -static int midi_capture_open(struct snd_rawmidi_substream *substream) +static int midi_open(struct snd_rawmidi_substream *substream) { struct snd_motu *motu = substream->rmidi->private_data; int err; @@ -29,44 +29,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) return err; } -static int midi_playback_open(struct snd_rawmidi_substream *substream) -{ - struct snd_motu *motu = substream->rmidi->private_data; - int err; - - err = snd_motu_stream_lock_try(motu); - if (err < 0) - return err; - - mutex_lock(&motu->mutex); - - motu->substreams_counter++; - err = snd_motu_stream_start_duplex(motu, 0); - - mutex_unlock(&motu->mutex); - - if (err < 0) - snd_motu_stream_lock_release(motu); - - return err; -} - -static int midi_capture_close(struct snd_rawmidi_substream *substream) -{ - struct snd_motu *motu = substream->rmidi->private_data; - - mutex_lock(&motu->mutex); - - motu->substreams_counter--; - snd_motu_stream_stop_duplex(motu); - - mutex_unlock(&motu->mutex); - - snd_motu_stream_lock_release(motu); - return 0; -} - -static int midi_playback_close(struct snd_rawmidi_substream *substream) +static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_motu *motu = substream->rmidi->private_data; @@ -129,13 +92,13 @@ static void set_midi_substream_names(struct snd_motu *motu, int snd_motu_create_midi_devices(struct snd_motu *motu) { static const struct snd_rawmidi_ops capture_ops = { - .open = midi_capture_open, - .close = midi_capture_close, + .open = midi_open, + .close = midi_close, .trigger = midi_capture_trigger, }; static const struct snd_rawmidi_ops playback_ops = { - .open = midi_playback_open, - .close = midi_playback_close, + .open = midi_open, + .close = midi_close, .trigger = midi_playback_trigger, }; struct snd_rawmidi *rmidi; From 8350132e399dacb212c506bea688a40df2101221 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:03 +0900 Subject: [PATCH 409/626] ALSA: firewire-motu: add helper function to keep isochronous resources This commit is a part of preparation to perform allocation/release of isochronous resources in pcm.hw_params/hw_free callbacks. This commit adds a helper function to allocate isochronous resources. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-stream.c | 67 +++++++++++++++++-------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index c136d7f8c49c..35b4e0f72fe2 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -26,48 +26,55 @@ #define RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000040 #define TX_PACKET_TRANSMISSION_SPEED_MASK 0x0000000f +static int keep_resources(struct snd_motu *motu, unsigned int rate, + struct amdtp_stream *stream) +{ + struct fw_iso_resources *resources; + struct snd_motu_packet_format *packet_format; + unsigned int midi_ports = 0; + int err; + + if (stream == &motu->rx_stream) { + resources = &motu->rx_resources; + packet_format = &motu->rx_packet_formats; + + if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) || + (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q)) + midi_ports = 1; + } else { + resources = &motu->tx_resources; + packet_format = &motu->tx_packet_formats; + + if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) || + (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q)) + midi_ports = 1; + } + + err = amdtp_motu_set_parameters(stream, rate, midi_ports, + packet_format); + if (err < 0) + return err; + + return fw_iso_resources_allocate(resources, + amdtp_stream_get_max_payload(stream), + fw_parent_device(motu->unit)->max_speed); +} + static int start_both_streams(struct snd_motu *motu, unsigned int rate) { - unsigned int midi_ports = 0; __be32 reg; u32 data; int err; - if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) || - (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q)) - midi_ports = 1; - - /* Set packet formation to our packet streaming engine. */ - err = amdtp_motu_set_parameters(&motu->rx_stream, rate, midi_ports, - &motu->rx_packet_formats); + err = keep_resources(motu, rate, &motu->tx_stream); if (err < 0) return err; - if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) || - (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q)) - midi_ports = 1; - else - midi_ports = 0; - - err = amdtp_motu_set_parameters(&motu->tx_stream, rate, midi_ports, - &motu->tx_packet_formats); + err = keep_resources(motu, rate, &motu->rx_stream); if (err < 0) return err; - /* Get isochronous resources on the bus. */ - err = fw_iso_resources_allocate(&motu->rx_resources, - amdtp_stream_get_max_payload(&motu->rx_stream), - fw_parent_device(motu->unit)->max_speed); - if (err < 0) - return err; - - err = fw_iso_resources_allocate(&motu->tx_resources, - amdtp_stream_get_max_payload(&motu->tx_stream), - fw_parent_device(motu->unit)->max_speed); - if (err < 0) - return err; - - /* Configure the unit to start isochronous communication. */ + // Configure the unit to start isochronous communication. err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, sizeof(reg)); if (err < 0) From fc49769af4fdba92e8e4f7429e05bb20b0639f90 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:04 +0900 Subject: [PATCH 410/626] ALSA: firewire-motu: code refactoring for condition to stop streaming In snd_motu_stream_start_duplex() function, there're two points to stop packet streaming, however they can be merged. This commit merges them. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-stream.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 35b4e0f72fe2..a3f45f2c817c 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -217,19 +217,11 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) if (motu->substreams_counter == 0) return 0; - /* Some packet queueing errors. */ - if (amdtp_streaming_error(&motu->rx_stream) || - amdtp_streaming_error(&motu->tx_stream)) { - amdtp_stream_stop(&motu->rx_stream); - amdtp_stream_stop(&motu->tx_stream); - stop_both_streams(motu); - } - err = snd_motu_stream_cache_packet_formats(motu); if (err < 0) return err; - /* Stop stream if rate is different. */ + // Stop stream if rate is different. err = protocol->get_clock_rate(motu, &curr_rate); if (err < 0) { dev_err(&motu->unit->device, @@ -238,7 +230,9 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) } if (rate == 0) rate = curr_rate; - if (rate != curr_rate) { + if (rate != curr_rate || + amdtp_streaming_error(&motu->rx_stream) || + amdtp_streaming_error(&motu->tx_stream)) { amdtp_stream_stop(&motu->rx_stream); amdtp_stream_stop(&motu->tx_stream); stop_both_streams(motu); From b66ab1428e68d0c1caea1c1d1490faadc21c2ac5 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:05 +0900 Subject: [PATCH 411/626] ALSA: firewire-motu: rename helper functions to begin/finish streaming session Like the other drivers in ALSA firewire stack, this commit renames functions to begin/finish packet streaming. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-stream.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index a3f45f2c817c..cb01f1d784f1 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -60,7 +60,7 @@ static int keep_resources(struct snd_motu *motu, unsigned int rate, fw_parent_device(motu->unit)->max_speed); } -static int start_both_streams(struct snd_motu *motu, unsigned int rate) +static int begin_session(struct snd_motu *motu, unsigned int rate) { __be32 reg; u32 data; @@ -91,7 +91,7 @@ static int start_both_streams(struct snd_motu *motu, unsigned int rate) sizeof(reg)); } -static void stop_both_streams(struct snd_motu *motu) +static void finish_session(struct snd_motu *motu) { __be32 reg; u32 data; @@ -235,7 +235,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) amdtp_streaming_error(&motu->tx_stream)) { amdtp_stream_stop(&motu->rx_stream); amdtp_stream_stop(&motu->tx_stream); - stop_both_streams(motu); + finish_session(motu); } if (!amdtp_stream_running(&motu->rx_stream)) { @@ -250,7 +250,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) if (err < 0) return err; - err = start_both_streams(motu, rate); + err = begin_session(motu, rate); if (err < 0) { dev_err(&motu->unit->device, "fail to start isochronous comm: %d\n", err); @@ -285,7 +285,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) return 0; stop_streams: - stop_both_streams(motu); + finish_session(motu); return err; } From e63a15185a7a5ac1fd65dd368de52196d66c0cac Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:06 +0900 Subject: [PATCH 412/626] ALSA: firewire-motu: minor code refactoring to stop isochronous context The helper function to stop isochronous context is superfluous. This commit removes it with simpler codes. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-stream.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index cb01f1d784f1..4fbec35eaad5 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -142,19 +142,6 @@ static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream) return 0; } -static void stop_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream) -{ - struct fw_iso_resources *resources; - - if (stream == &motu->rx_stream) - resources = &motu->rx_resources; - else - resources = &motu->tx_resources; - - amdtp_stream_stop(stream); - fw_iso_resources_free(resources); -} - int snd_motu_stream_cache_packet_formats(struct snd_motu *motu) { int err; @@ -292,11 +279,11 @@ stop_streams: void snd_motu_stream_stop_duplex(struct snd_motu *motu) { if (motu->substreams_counter == 0) { - if (amdtp_stream_running(&motu->tx_stream)) - stop_isoc_ctx(motu, &motu->tx_stream); + amdtp_stream_stop(&motu->tx_stream); + amdtp_stream_stop(&motu->rx_stream); - if (amdtp_stream_running(&motu->rx_stream)) - stop_isoc_ctx(motu, &motu->rx_stream); + fw_iso_resources_free(&motu->tx_resources); + fw_iso_resources_free(&motu->rx_resources); } } From ec694fba2ac9406cb3fc3c3216db3de9ed3174a7 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:07 +0900 Subject: [PATCH 413/626] ALSA: firewire-motu: code refactoring to finish streaming session The operation to finish packet streaming includes stopping isochronous contexts. This commit merges it to the helper function. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-stream.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 4fbec35eaad5..53c43848b137 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -101,6 +101,9 @@ static void finish_session(struct snd_motu *motu) if (err < 0) return; + amdtp_stream_stop(&motu->tx_stream); + amdtp_stream_stop(&motu->rx_stream); + err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, sizeof(reg)); if (err < 0) @@ -219,11 +222,8 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) rate = curr_rate; if (rate != curr_rate || amdtp_streaming_error(&motu->rx_stream) || - amdtp_streaming_error(&motu->tx_stream)) { - amdtp_stream_stop(&motu->rx_stream); - amdtp_stream_stop(&motu->tx_stream); + amdtp_streaming_error(&motu->tx_stream)) finish_session(motu); - } if (!amdtp_stream_running(&motu->rx_stream)) { err = protocol->set_clock_rate(motu, rate); @@ -278,13 +278,8 @@ stop_streams: void snd_motu_stream_stop_duplex(struct snd_motu *motu) { - if (motu->substreams_counter == 0) { - amdtp_stream_stop(&motu->tx_stream); - amdtp_stream_stop(&motu->rx_stream); - - fw_iso_resources_free(&motu->tx_resources); - fw_iso_resources_free(&motu->rx_resources); - } + if (motu->substreams_counter == 0) + finish_session(motu); } static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir) From 8edc56ec8f14a586a55b2ab2fda76e6bf4738ee6 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:08 +0900 Subject: [PATCH 414/626] ALSA: firewire-motu: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Once allocated, isochronous resources are available for packet streaming, even if the streaming is cancelled. For this reason, current implementation handles allocation of the resources and starting packet streaming at the same time. However, this brings complicated procedure to start packet streaming. This commit separates the allocation and starting. The allocation is done in pcm.hw_params callback and available till pcm.hw_free callback. Even if any XRUN occurs, pcm.prepare callback is done to restart packet streaming without releasing/allocating the resources. There are two points to stop packet streaming; in pcm.hw_params and pcm.prepare callbacks. The former point is a case that packet streaming is already started for any MIDI substream then packet streaming is requested with different sampling transfer frequency for any PCM substream. The latter point is cases of any XRUN or packet queueing error. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-midi.c | 10 ++- sound/firewire/motu/motu-pcm.c | 26 +++++--- sound/firewire/motu/motu-stream.c | 100 +++++++++++++++++------------- sound/firewire/motu/motu.h | 4 +- 4 files changed, 84 insertions(+), 56 deletions(-) diff --git a/sound/firewire/motu/motu-midi.c b/sound/firewire/motu/motu-midi.c index 3b205386ed24..a463730c72bc 100644 --- a/sound/firewire/motu/motu-midi.c +++ b/sound/firewire/motu/motu-midi.c @@ -18,8 +18,11 @@ static int midi_open(struct snd_rawmidi_substream *substream) mutex_lock(&motu->mutex); - motu->substreams_counter++; - err = snd_motu_stream_start_duplex(motu, 0); + err = snd_motu_stream_reserve_duplex(motu, 0); + if (err >= 0) { + ++motu->substreams_counter; + err = snd_motu_stream_start_duplex(motu); + } mutex_unlock(&motu->mutex); @@ -35,8 +38,9 @@ static int midi_close(struct snd_rawmidi_substream *substream) mutex_lock(&motu->mutex); - motu->substreams_counter--; + --motu->substreams_counter; snd_motu_stream_stop_duplex(motu); + snd_motu_stream_release_duplex(motu); mutex_unlock(&motu->mutex); diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index b0e5ebf05bec..d4e75d3ee928 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -202,12 +202,16 @@ static int capture_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&motu->mutex); - motu->substreams_counter++; + err = snd_motu_stream_reserve_duplex(motu, rate); + if (err >= 0) + ++motu->substreams_counter; mutex_unlock(&motu->mutex); } - return 0; + return err; } static int playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) @@ -221,12 +225,16 @@ static int playback_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&motu->mutex); - motu->substreams_counter++; + err = snd_motu_stream_reserve_duplex(motu, rate); + if (err >= 0) + ++motu->substreams_counter; mutex_unlock(&motu->mutex); } - return 0; + return err; } static int capture_hw_free(struct snd_pcm_substream *substream) @@ -236,9 +244,10 @@ static int capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&motu->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - motu->substreams_counter--; + --motu->substreams_counter; snd_motu_stream_stop_duplex(motu); + snd_motu_stream_release_duplex(motu); mutex_unlock(&motu->mutex); @@ -252,9 +261,10 @@ static int playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&motu->mutex); if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - motu->substreams_counter--; + --motu->substreams_counter; snd_motu_stream_stop_duplex(motu); + snd_motu_stream_release_duplex(motu); mutex_unlock(&motu->mutex); @@ -267,7 +277,7 @@ static int capture_prepare(struct snd_pcm_substream *substream) int err; mutex_lock(&motu->mutex); - err = snd_motu_stream_start_duplex(motu, substream->runtime->rate); + err = snd_motu_stream_start_duplex(motu); mutex_unlock(&motu->mutex); if (err >= 0) amdtp_stream_pcm_prepare(&motu->tx_stream); @@ -280,7 +290,7 @@ static int playback_prepare(struct snd_pcm_substream *substream) int err; mutex_lock(&motu->mutex); - err = snd_motu_stream_start_duplex(motu, substream->runtime->rate); + err = snd_motu_stream_start_duplex(motu); mutex_unlock(&motu->mutex); if (err >= 0) amdtp_stream_pcm_prepare(&motu->rx_stream); diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 53c43848b137..5630a8f1f2f1 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -60,20 +60,12 @@ static int keep_resources(struct snd_motu *motu, unsigned int rate, fw_parent_device(motu->unit)->max_speed); } -static int begin_session(struct snd_motu *motu, unsigned int rate) +static int begin_session(struct snd_motu *motu) { __be32 reg; u32 data; int err; - err = keep_resources(motu, rate, &motu->tx_stream); - if (err < 0) - return err; - - err = keep_resources(motu, rate, &motu->rx_stream); - if (err < 0) - return err; - // Configure the unit to start isochronous communication. err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, sizeof(reg)); @@ -116,9 +108,6 @@ static void finish_session(struct snd_motu *motu) reg = cpu_to_be32(data); snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, ®, sizeof(reg)); - - fw_iso_resources_free(&motu->tx_resources); - fw_iso_resources_free(&motu->rx_resources); } static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream) @@ -136,11 +125,8 @@ static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream) if (err < 0) return err; - if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { - amdtp_stream_stop(stream); - fw_iso_resources_free(resources); + if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) return -ETIMEDOUT; - } return 0; } @@ -172,6 +158,56 @@ int snd_motu_stream_cache_packet_formats(struct snd_motu *motu) return 0; } +int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate) +{ + unsigned int curr_rate; + int err; + + err = motu->spec->protocol->get_clock_rate(motu, &curr_rate); + if (err < 0) + return err; + if (rate == 0) + rate = curr_rate; + + if (motu->substreams_counter == 0 || curr_rate != rate) { + finish_session(motu); + + fw_iso_resources_free(&motu->tx_resources); + fw_iso_resources_free(&motu->rx_resources); + + err = motu->spec->protocol->set_clock_rate(motu, rate); + if (err < 0) { + dev_err(&motu->unit->device, + "fail to set sampling rate: %d\n", err); + return err; + } + + err = snd_motu_stream_cache_packet_formats(motu); + if (err < 0) + return err; + + err = keep_resources(motu, rate, &motu->tx_stream); + if (err < 0) + return err; + + err = keep_resources(motu, rate, &motu->rx_stream); + if (err < 0) { + fw_iso_resources_free(&motu->tx_resources); + return err; + } + } + + return 0; +} + +void snd_motu_stream_release_duplex(struct snd_motu *motu) +{ + if (motu->substreams_counter == 0) { + fw_iso_resources_free(&motu->tx_resources); + fw_iso_resources_free(&motu->rx_resources); + } +} + static int ensure_packet_formats(struct snd_motu *motu) { __be32 reg; @@ -198,46 +234,23 @@ static int ensure_packet_formats(struct snd_motu *motu) sizeof(reg)); } -int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) +int snd_motu_stream_start_duplex(struct snd_motu *motu) { - const struct snd_motu_protocol *protocol = motu->spec->protocol; - unsigned int curr_rate; int err = 0; if (motu->substreams_counter == 0) return 0; - err = snd_motu_stream_cache_packet_formats(motu); - if (err < 0) - return err; - - // Stop stream if rate is different. - err = protocol->get_clock_rate(motu, &curr_rate); - if (err < 0) { - dev_err(&motu->unit->device, - "fail to get sampling rate: %d\n", err); - return err; - } - if (rate == 0) - rate = curr_rate; - if (rate != curr_rate || - amdtp_streaming_error(&motu->rx_stream) || + if (amdtp_streaming_error(&motu->rx_stream) || amdtp_streaming_error(&motu->tx_stream)) finish_session(motu); if (!amdtp_stream_running(&motu->rx_stream)) { - err = protocol->set_clock_rate(motu, rate); - if (err < 0) { - dev_err(&motu->unit->device, - "fail to set sampling rate: %d\n", err); - return err; - } - err = ensure_packet_formats(motu); if (err < 0) return err; - err = begin_session(motu, rate); + err = begin_session(motu); if (err < 0) { dev_err(&motu->unit->device, "fail to start isochronous comm: %d\n", err); @@ -251,7 +264,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) goto stop_streams; } - err = protocol->switch_fetching_mode(motu, true); + err = motu->spec->protocol->switch_fetching_mode(motu, true); if (err < 0) { dev_err(&motu->unit->device, "fail to enable frame fetching: %d\n", err); @@ -264,7 +277,6 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) if (err < 0) { dev_err(&motu->unit->device, "fail to start IR context: %d", err); - amdtp_stream_stop(&motu->rx_stream); goto stop_streams; } } diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index ae4b37cdfade..32cd42873fd0 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -153,7 +153,9 @@ void snd_motu_transaction_unregister(struct snd_motu *motu); int snd_motu_stream_init_duplex(struct snd_motu *motu); void snd_motu_stream_destroy_duplex(struct snd_motu *motu); int snd_motu_stream_cache_packet_formats(struct snd_motu *motu); -int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate); +int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate); +void snd_motu_stream_release_duplex(struct snd_motu *motu); +int snd_motu_stream_start_duplex(struct snd_motu *motu); void snd_motu_stream_stop_duplex(struct snd_motu *motu); int snd_motu_stream_lock_try(struct snd_motu *motu); void snd_motu_stream_lock_release(struct snd_motu *motu); From 2d103420c6eae2ef7d464798242f0d5283526054 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:09 +0900 Subject: [PATCH 415/626] ALSA: firewire-motu: update isochronous resources when starting packet streaming after bus-reset After bus reset, isochronous resource manager releases all of allocated isochronous resources. The nodes to transfer isochronous packet should request reallocation of the resources. However, between the bus-reset and invocation of 'struct fw_driver.update' handler, ALSA PCM application can detect this situation by XRUN because the target device cancelled to transmit packets once bus-reset occurs. Due to the above mechanism, ALSA fireface driver just stops packet streaming in the update handler, thus pcm.prepare handler should request the reallocation. This commit requests the reallocation in pcm.prepare callback when bus generation is changed. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-stream.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 5630a8f1f2f1..82891583b736 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -236,6 +236,7 @@ static int ensure_packet_formats(struct snd_motu *motu) int snd_motu_stream_start_duplex(struct snd_motu *motu) { + unsigned int generation = motu->rx_resources.generation; int err = 0; if (motu->substreams_counter == 0) @@ -245,6 +246,16 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) amdtp_streaming_error(&motu->tx_stream)) finish_session(motu); + if (generation != fw_parent_device(motu->unit)->card->generation) { + err = fw_iso_resources_update(&motu->rx_resources); + if (err < 0) + return err; + + err = fw_iso_resources_update(&motu->tx_resources); + if (err < 0) + return err; + } + if (!amdtp_stream_running(&motu->rx_stream)) { err = ensure_packet_formats(motu); if (err < 0) From 15d472ecc510e20e42337c8205fa3987329e488d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 17 Jun 2019 17:15:10 +0900 Subject: [PATCH 416/626] ALSA: firewire-motu: code refactoring for pcm.hw_params/hw_free callbacks The pairs of pcm.hw_params callbacks and .hw_free callbacks for both direction have no differences. This commit unifies the pairs. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-pcm.c | 54 +++++----------------------------- 1 file changed, 7 insertions(+), 47 deletions(-) diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index d4e75d3ee928..b9852c911b98 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -190,31 +190,8 @@ static int pcm_close(struct snd_pcm_substream *substream) return 0; } -static int capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_motu *motu = substream->private_data; - int err; - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { - unsigned int rate = params_rate(hw_params); - - mutex_lock(&motu->mutex); - err = snd_motu_stream_reserve_duplex(motu, rate); - if (err >= 0) - ++motu->substreams_counter; - mutex_unlock(&motu->mutex); - } - - return err; -} -static int playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_motu *motu = substream->private_data; int err; @@ -237,24 +214,7 @@ static int playback_hw_params(struct snd_pcm_substream *substream, return err; } -static int capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_motu *motu = substream->private_data; - - mutex_lock(&motu->mutex); - - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - --motu->substreams_counter; - - snd_motu_stream_stop_duplex(motu); - snd_motu_stream_release_duplex(motu); - - mutex_unlock(&motu->mutex); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static int playback_hw_free(struct snd_pcm_substream *substream) +static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_motu *motu = substream->private_data; @@ -366,8 +326,8 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = capture_hw_params, - .hw_free = capture_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = capture_prepare, .trigger = capture_trigger, .pointer = capture_pointer, @@ -378,8 +338,8 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = playback_hw_params, - .hw_free = playback_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = playback_prepare, .trigger = playback_trigger, .pointer = playback_pointer, From 7a1954de3050cb13cf9ee43493ea45785dae68a2 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 13 Jun 2019 21:04:30 +0200 Subject: [PATCH 417/626] ASoC: Intel: Skylake: Fix incorrect capture position reporting HW recommends to set DUM bit on device power up, so that DPIB write request occurs every frame regardless of whether DPIB has changed or not. This addresses incorrect position reporting for capture streams. Signed-off-by: Leoni Prodduvaka Signed-off-by: Cezary Rojewski Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 21 +++++++++++++++++++++ sound/soc/intel/skylake/skl.h | 1 + 2 files changed, 22 insertions(+) diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 4ed5b7e17d44..16f4372ce437 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -192,6 +192,25 @@ void skl_update_d0i3c(struct device *dev, bool enable) snd_hdac_chip_readb(bus, VS_D0I3C)); } +/** + * skl_dum_set - set DUM bit in EM2 register + * @bus: HD-audio core bus + * + * Addresses incorrect position reporting for capture streams. + * Used on device power up. + */ +static void skl_dum_set(struct hdac_bus *bus) +{ + /* For the DUM bit to be set, CRST needs to be out of reset state */ + if (!(snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET)) { + skl_enable_miscbdcge(bus->dev, false); + snd_hdac_bus_exit_link_reset(bus); + skl_enable_miscbdcge(bus->dev, true); + } + + snd_hdac_chip_updatel(bus, VS_EM2, AZX_VS_EM2_DUM, AZX_VS_EM2_DUM); +} + /* called from IRQ */ static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr) { @@ -299,6 +318,7 @@ static int _skl_resume(struct hdac_bus *bus) struct skl *skl = bus_to_skl(bus); skl_init_pci(skl); + skl_dum_set(bus); skl_init_chip(bus, true); return skl_resume_dsp(skl); @@ -956,6 +976,7 @@ static int skl_first_init(struct hdac_bus *bus) /* initialize chip */ skl_init_pci(skl); + skl_dum_set(bus); return skl_init_chip(bus, true); } diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 85f8bb6687dc..b92a7f8fe675 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -46,6 +46,7 @@ #define DMA_TRANSMITION_START 2 #define DMA_TRANSMITION_STOP 3 +#define AZX_VS_EM2_DUM BIT(23) #define AZX_REG_VS_EM2_L1SEN BIT(13) struct skl_dsp_resource { From c054b41690a44e6534eb2a1beda1b655f3994c5b Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 17 Jun 2019 22:29:09 -0700 Subject: [PATCH 418/626] ASoC: qcom: common: Mark links as nonatomic The interface used to communicate with the DSP can sleep, so mark the links as nonatomic. This prevents various sleep while atomic errors when bringing up the audio interface. Suggested-by: Srinivas Kandagatla Signed-off-by: Bjorn Andersson Signed-off-by: Mark Brown --- sound/soc/qcom/common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 5661025e8cec..a612d860ad26 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -97,6 +97,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) goto err; } + link->nonatomic = 1; link->dpcm_playback = 1; link->dpcm_capture = 1; link->stream_name = link->name; From 281c443f1e8e25ebc46aaebf48c73e0545a0830e Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Tue, 18 Jun 2019 15:04:26 +0800 Subject: [PATCH 419/626] ASoC: Intel: sof_rt5682: use GFP_KERNEL instead of GFP_ATOMIC Change the memory allocation flag from GFP_ATOMIC to GFP_KERNEL because probe of platform device is unlikely a place where cannot sleep. Signed-off-by: Tzung-Bi Shih Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 3343dbcd506f..90d262ebeb10 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -494,7 +494,7 @@ static int sof_audio_probe(struct platform_device *pdev) int dmic_num, hdmi_num; int ret, ssp_amp, ssp_codec; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; From ac28ec07ae1c5c1e18ed6855eb105a328418da88 Mon Sep 17 00:00:00 2001 From: Nilkanth Ahirrao Date: Tue, 18 Jun 2019 14:19:53 +0900 Subject: [PATCH 420/626] ASoC: rsnd: fixup mod ID calculation in rsnd_ctu_probe_ commit c16015f36cc1 ("ASoC: rsnd: add .get_id/.get_id_sub") introduces rsnd_ctu_id which calcualates and gives the main Device id of the CTU by dividing the id by 4. rsnd_mod_id uses this interface to get the CTU main Device id. But this commit forgets to revert the main Device id calcution previously done in rsnd_ctu_probe_ which also divides the id by 4. This path corrects the same to get the correct main Device id. The issue is observered when rsnd_ctu_probe_ is done for CTU1 Fixes: c16015f36cc1 ("ASoC: rsnd: add .get_id/.get_id_sub") Signed-off-by: Nilkanth Ahirrao Signed-off-by: Suresh Udipi Signed-off-by: Jiada Wang Acked-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ctu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 8cb06dab234e..7647b3d4c0ba 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -108,7 +108,7 @@ static int rsnd_ctu_probe_(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { - return rsnd_cmd_attach(io, rsnd_mod_id(mod) / 4); + return rsnd_cmd_attach(io, rsnd_mod_id(mod)); } static void rsnd_ctu_value_init(struct rsnd_dai_stream *io, From 5f174cf75a8cb14d50c1cecfb3884ae82f754058 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:27:52 +0900 Subject: [PATCH 421/626] ASoC: soc.h: fixup for_each_card_links() macro Macro is using "link", not "dai_link" Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 055e6d035e04..80c1ca3a62c7 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1230,7 +1230,7 @@ struct snd_soc_card { (i)++) #define for_each_card_links(card, link) \ - list_for_each_entry(dai_link, &(card)->dai_link_list, list) + list_for_each_entry(link, &(card)->dai_link_list, list) #define for_each_card_links_safe(card, link, _link) \ list_for_each_entry_safe(link, _link, &(card)->dai_link_list, list) From 1eed6bc03f5409f0367780d4045bf3036e51b7ee Mon Sep 17 00:00:00 2001 From: Xun Zhang Date: Wed, 19 Jun 2019 02:15:38 +0800 Subject: [PATCH 422/626] ASoC: Intel: sof-rt5682: add MCLK support for BYT platform The sof-rt5682 machine driver currently uses BCLK on BYT/Minnowboard platform. The MCLK signal is available since the Turbot revision, so enable MCLK on BYT/Minnowboard Turbot platform. Signed-off-by: Xun Zhang Signed-off-by: Bard liao Acked-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 65 ++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index e2e5f97d9920..f3d481b75b15 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ #define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6)) #define SOF_RT5682_SSP_AMP(quirk) \ (((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK) +#define SOF_RT5682_MCLK_BYTCHT_EN BIT(9) /* Default: MCLK on, MCLK 19.2M, SSP0 */ static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | @@ -48,6 +50,7 @@ struct sof_hdmi_pcm { }; struct sof_card_private { + struct clk *mclk; struct snd_soc_jack sof_headset; struct list_head hdmi_pcm_list; }; @@ -59,6 +62,22 @@ static int sof_rt5682_quirk_cb(const struct dmi_system_id *id) } static const struct dmi_system_id sof_rt5682_quirk_table[] = { + { + .callback = sof_rt5682_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), + DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"), + }, + .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)), + }, + { + .callback = sof_rt5682_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"), + }, + .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)), + }, { .callback = sof_rt5682_quirk_cb, .matches = { @@ -127,6 +146,27 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) RT5682_CLK_SEL_I2S1_ASRC); } + if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { + /* + * The firmware might enable the clock at + * boot (this information may or may not + * be reflected in the enable clock register). + * To change the rate we must disable the clock + * first to cover these cases. Due to common + * clock framework restrictions that do not allow + * to disable a clock that has not been enabled, + * we need to enable the clock first. + */ + ret = clk_prepare_enable(ctx->mclk); + if (!ret) + clk_disable_unprepare(ctx->mclk); + + ret = clk_set_rate(ctx->mclk, 19200000); + + if (ret) + dev_err(rtd->dev, "unable to set MCLK rate\n"); + } + /* * Headset buttons map to the google Reference headset. * These can be configured by userspace. @@ -161,10 +201,20 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec_dai = rtd->codec_dai; int clk_id, clk_freq, pll_out, ret; if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) { + if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { + ret = clk_prepare_enable(ctx->mclk); + if (ret < 0) { + dev_err(rtd->dev, + "could not configure MCLK state"); + return ret; + } + } + clk_id = RT5682_PLL1_S_MCLK; if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ) clk_freq = 24000000; @@ -507,7 +557,9 @@ static int sof_audio_probe(struct platform_device *pdev) dmic_num = 0; hdmi_num = 0; /* default quirk for legacy cpu */ - sof_rt5682_quirk = SOF_RT5682_SSP_CODEC(2); + sof_rt5682_quirk = SOF_RT5682_MCLK_EN | + SOF_RT5682_MCLK_BYTCHT_EN | + SOF_RT5682_SSP_CODEC(2); } else { dmic_num = 1; hdmi_num = 3; @@ -515,6 +567,17 @@ static int sof_audio_probe(struct platform_device *pdev) dmi_check_system(sof_rt5682_quirk_table); + /* need to get main clock from pmc */ + if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { + ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); + ret = clk_prepare_enable(ctx->mclk); + if (ret < 0) { + dev_err(&pdev->dev, + "could not configure MCLK state"); + return ret; + } + } + dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk); ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >> From e711223ad35b326a597ebd3a6acc8276fd38e25c Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 19 Jun 2019 02:15:39 +0800 Subject: [PATCH 423/626] ASoC: Intel: sof-rt5682: correct naming for dmic16k Change the link name to be "dmic16k", the cpu_dai_name to be "DMIC16k Pin", to be aligned with other machine drivers. Signed-off-by: Keyon Jie Signed-off-by: Bard liao Acked-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 39 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index f3d481b75b15..64db00353e18 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -377,7 +377,7 @@ static struct snd_soc_dai_link_component max98357a_component[] = { static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, int ssp_codec, int ssp_amp, - int dmic_num, + int dmic_be_num, int hdmi_num) { struct snd_soc_dai_link_component *idisp_components; @@ -437,20 +437,23 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, id++; /* dmic */ - for (i = 1; i <= dmic_num; i++) { - links[id].name = devm_kasprintf(dev, GFP_KERNEL, - "dmic%02d", i); - if (!links[id].name) - goto devm_err; - - links[id].id = id; + if (dmic_be_num > 0) { + /* at least we have dmic01 */ + links[id].name = "dmic01"; links[id].cpus = &cpus[id]; - links[id].num_cpus = 1; - links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, - "DMIC%02d Pin", i); - if (!links[id].cpus->dai_name) - goto devm_err; + links[id].cpus->dai_name = "DMIC01 Pin"; + if (dmic_be_num > 1) { + /* set up 2 BE links at most */ + links[id + 1].name = "dmic16k"; + links[id + 1].cpus = &cpus[id + 1]; + links[id + 1].cpus->dai_name = "DMIC16k Pin"; + dmic_be_num = 2; + } + } + for (i = 0; i < dmic_be_num; i++) { + links[id].id = id; + links[id].num_cpus = 1; links[id].codecs = dmic_component; links[id].num_codecs = ARRAY_SIZE(dmic_component); links[id].platforms = platform_component; @@ -545,7 +548,7 @@ static int sof_audio_probe(struct platform_device *pdev) struct snd_soc_dai_link *dai_links; struct snd_soc_acpi_mach *mach; struct sof_card_private *ctx; - int dmic_num, hdmi_num; + int dmic_be_num, hdmi_num; int ret, ssp_amp, ssp_codec; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); @@ -554,14 +557,14 @@ static int sof_audio_probe(struct platform_device *pdev) if (soc_intel_is_byt() || soc_intel_is_cht()) { is_legacy_cpu = 1; - dmic_num = 0; + dmic_be_num = 0; hdmi_num = 0; /* default quirk for legacy cpu */ sof_rt5682_quirk = SOF_RT5682_MCLK_EN | SOF_RT5682_MCLK_BYTCHT_EN | SOF_RT5682_SSP_CODEC(2); } else { - dmic_num = 1; + dmic_be_num = 2; hdmi_num = 3; } @@ -586,13 +589,13 @@ static int sof_audio_probe(struct platform_device *pdev) ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK; /* compute number of dai links */ - sof_audio_card_rt5682.num_links = 1 + dmic_num + hdmi_num; + sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num; if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) sof_audio_card_rt5682.num_links++; dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp, - dmic_num, hdmi_num); + dmic_be_num, hdmi_num); if (!dai_links) return -ENOMEM; From 16395ceee11f8f8af764bac76adc20a43ba1a153 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 17 Jun 2019 22:28:13 -0700 Subject: [PATCH 424/626] ASoC: qcom: common: Fix NULL pointer in of parser A snd_soc_dai_link_component is allocated and associated with the first link, so when the code tries to assign the of_node of the second link's "cpu" member it dereferences a NULL pointer. Fix this by moving the allocation and assignement of snd_soc_dai_link_components into the loop, giving us one pair per link. Fixes: 1e36ea360ab9 ("ASoC: qcom: common: use modern dai_link style") Signed-off-by: Bjorn Andersson Acked-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/common.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index c7a878507220..97488b5cc515 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -42,17 +42,17 @@ int qcom_snd_parse_of(struct snd_soc_card *card) card->num_links = num_links; link = card->dai_link; - dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); - if (!dlc) - return -ENOMEM; - - link->cpus = &dlc[0]; - link->platforms = &dlc[1]; - - link->num_cpus = 1; - link->num_platforms = 1; - for_each_child_of_node(dev->of_node, np) { + dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return -ENOMEM; + + link->cpus = &dlc[0]; + link->platforms = &dlc[1]; + + link->num_cpus = 1; + link->num_platforms = 1; + cpu = of_get_child_by_name(np, "cpu"); platform = of_get_child_by_name(np, "platform"); codec = of_get_child_by_name(np, "codec"); From 4f7b018b55db0361718161e1471d8b7a16fdfa47 Mon Sep 17 00:00:00 2001 From: Ben Zhang Date: Tue, 18 Jun 2019 17:45:54 -0600 Subject: [PATCH 425/626] ASoC: rt5677: clear interrupts by polarity flip The rt5677 jack detection function has a requirement that the polarity of an interrupt be flipped after it fires in order to clear the interrupt. This patch implements an irq_chip with irq_domain directly instead of using regmap-irq, so that interrupt source line polarities can be flipped in the irq handler. The reason that this patch does not add this feature within regmap-irq is that future patches will add hotword detection support to this irq handler. Those patches will require adding additional logic that would not make sense to have in regmap-irq. Signed-off-by: Ben Zhang Signed-off-by: Fletcher Woodruff Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 173 ++++++++++++++++++++++++++++++-------- sound/soc/codecs/rt5677.h | 8 +- 2 files changed, 145 insertions(+), 36 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 87a92ba0d040..b5ae61ff87af 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -23,6 +23,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -4620,7 +4624,6 @@ static void rt5677_gpio_config(struct rt5677_priv *rt5677, unsigned offset, static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) { struct rt5677_priv *rt5677 = gpiochip_get_data(chip); - struct regmap_irq_chip_data *data = rt5677->irq_data; int irq; if ((rt5677->pdata.jd1_gpio == 1 && offset == RT5677_GPIO1) || @@ -4646,7 +4649,7 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) return -ENXIO; } - return regmap_irq_get_virq(data, irq); + return irq_create_mapping(rt5677->domain, irq); } static const struct gpio_chip rt5677_template_chip = { @@ -5042,30 +5045,130 @@ static void rt5677_read_device_properties(struct rt5677_priv *rt5677, rt5677->pdata.jd3_gpio = val; } -static struct regmap_irq rt5677_irqs[] = { +struct rt5677_irq_desc { + unsigned int enable_mask; + unsigned int status_mask; + unsigned int polarity_mask; +}; + +static const struct rt5677_irq_desc rt5677_irq_descs[] = { [RT5677_IRQ_JD1] = { - .reg_offset = 0, - .mask = RT5677_EN_IRQ_GPIO_JD1, + .enable_mask = RT5677_EN_IRQ_GPIO_JD1, + .status_mask = RT5677_STA_GPIO_JD1, + .polarity_mask = RT5677_INV_GPIO_JD1, }, [RT5677_IRQ_JD2] = { - .reg_offset = 0, - .mask = RT5677_EN_IRQ_GPIO_JD2, + .enable_mask = RT5677_EN_IRQ_GPIO_JD2, + .status_mask = RT5677_STA_GPIO_JD2, + .polarity_mask = RT5677_INV_GPIO_JD2, }, [RT5677_IRQ_JD3] = { - .reg_offset = 0, - .mask = RT5677_EN_IRQ_GPIO_JD3, + .enable_mask = RT5677_EN_IRQ_GPIO_JD3, + .status_mask = RT5677_STA_GPIO_JD3, + .polarity_mask = RT5677_INV_GPIO_JD3, }, }; -static struct regmap_irq_chip rt5677_irq_chip = { - .name = RT5677_DRV_NAME, - .irqs = rt5677_irqs, - .num_irqs = ARRAY_SIZE(rt5677_irqs), +static irqreturn_t rt5677_irq(int unused, void *data) +{ + struct rt5677_priv *rt5677 = data; + int ret = 0, i, reg_irq, virq; + bool irq_fired = false; - .num_regs = 1, - .status_base = RT5677_IRQ_CTRL1, - .mask_base = RT5677_IRQ_CTRL1, - .mask_invert = 1, + mutex_lock(&rt5677->irq_lock); + /* Read interrupt status */ + ret = regmap_read(rt5677->regmap, RT5677_IRQ_CTRL1, ®_irq); + if (ret) { + dev_err(rt5677->dev, "failed reading IRQ status: %d\n", ret); + goto exit; + } + + for (i = 0; i < RT5677_IRQ_NUM; i++) { + if (reg_irq & rt5677_irq_descs[i].status_mask) { + irq_fired = true; + virq = irq_find_mapping(rt5677->domain, i); + if (virq) + handle_nested_irq(virq); + + /* Clear the interrupt by flipping the polarity of the + * interrupt source line that fired + */ + reg_irq ^= rt5677_irq_descs[i].polarity_mask; + } + } + + if (!irq_fired) + goto exit; + + ret = regmap_write(rt5677->regmap, RT5677_IRQ_CTRL1, reg_irq); + if (ret) { + dev_err(rt5677->dev, "failed updating IRQ status: %d\n", ret); + goto exit; + } +exit: + mutex_unlock(&rt5677->irq_lock); + if (irq_fired) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static void rt5677_irq_bus_lock(struct irq_data *data) +{ + struct rt5677_priv *rt5677 = irq_data_get_irq_chip_data(data); + + mutex_lock(&rt5677->irq_lock); +} + +static void rt5677_irq_bus_sync_unlock(struct irq_data *data) +{ + struct rt5677_priv *rt5677 = irq_data_get_irq_chip_data(data); + + // Set the enable/disable bits for the jack detect IRQs. + regmap_update_bits(rt5677->regmap, RT5677_IRQ_CTRL1, + RT5677_EN_IRQ_GPIO_JD1 | RT5677_EN_IRQ_GPIO_JD2 | + RT5677_EN_IRQ_GPIO_JD3, rt5677->irq_en); + mutex_unlock(&rt5677->irq_lock); +} + +static void rt5677_irq_enable(struct irq_data *data) +{ + struct rt5677_priv *rt5677 = irq_data_get_irq_chip_data(data); + + rt5677->irq_en |= rt5677_irq_descs[data->hwirq].enable_mask; +} + +static void rt5677_irq_disable(struct irq_data *data) +{ + struct rt5677_priv *rt5677 = irq_data_get_irq_chip_data(data); + + rt5677->irq_en &= ~rt5677_irq_descs[data->hwirq].enable_mask; +} + +static struct irq_chip rt5677_irq_chip = { + .name = "rt5677_irq_chip", + .irq_bus_lock = rt5677_irq_bus_lock, + .irq_bus_sync_unlock = rt5677_irq_bus_sync_unlock, + .irq_disable = rt5677_irq_disable, + .irq_enable = rt5677_irq_enable, +}; + +static int rt5677_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct rt5677_priv *rt5677 = h->host_data; + + irq_set_chip_data(virq, rt5677); + irq_set_chip(virq, &rt5677_irq_chip); + irq_set_nested_thread(virq, 1); + irq_set_noprobe(virq); + return 0; +} + + +static const struct irq_domain_ops rt5677_domain_ops = { + .map = rt5677_irq_map, + .xlate = irq_domain_xlate_twocell, }; static int rt5677_init_irq(struct i2c_client *i2c) @@ -5084,6 +5187,8 @@ static int rt5677_init_irq(struct i2c_client *i2c) return -EINVAL; } + mutex_init(&rt5677->irq_lock); + /* * Select RC as the debounce clock so that GPIO works even when * MCLK is gated which happens when there is no audio stream @@ -5092,7 +5197,6 @@ static int rt5677_init_irq(struct i2c_client *i2c) regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, RT5677_IRQ_DEBOUNCE_SEL_MASK, RT5677_IRQ_DEBOUNCE_SEL_RC); - /* Enable auto power on RC when GPIO states are changed */ regmap_update_bits(rt5677->regmap, RT5677_GEN_CTRL1, 0xff, 0xff); @@ -5115,24 +5219,21 @@ static int rt5677_init_irq(struct i2c_client *i2c) regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL1, RT5677_GPIO1_PIN_MASK, RT5677_GPIO1_PIN_IRQ); - ret = regmap_add_irq_chip(rt5677->regmap, i2c->irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0, - &rt5677_irq_chip, &rt5677->irq_data); - - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register IRQ chip: %d\n", ret); - return ret; + /* Ready to listen for interrupts */ + rt5677->domain = irq_domain_add_linear(i2c->dev.of_node, + RT5677_IRQ_NUM, &rt5677_domain_ops, rt5677); + if (!rt5677->domain) { + dev_err(&i2c->dev, "Failed to create IRQ domain\n"); + return -ENOMEM; } - return 0; -} + ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, rt5677_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "rt5677", rt5677); + if (ret) + dev_err(&i2c->dev, "Failed to request IRQ: %d\n", ret); -static void rt5677_free_irq(struct i2c_client *i2c) -{ - struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c); - - if (rt5677->irq_data) - regmap_del_irq_chip(i2c->irq, rt5677->irq_data); + return ret; } static int rt5677_i2c_probe(struct i2c_client *i2c) @@ -5146,6 +5247,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c) if (rt5677 == NULL) return -ENOMEM; + rt5677->dev = &i2c->dev; i2c_set_clientdata(i2c, rt5677); if (i2c->dev.of_node) { @@ -5259,7 +5361,9 @@ static int rt5677_i2c_probe(struct i2c_client *i2c) RT5677_MICBIAS1_CTRL_VDD_3_3V); rt5677_init_gpio(i2c); - rt5677_init_irq(i2c); + ret = rt5677_init_irq(i2c); + if (ret) + dev_err(&i2c->dev, "Failed to initialize irq: %d\n", ret); return devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5677, @@ -5268,7 +5372,6 @@ static int rt5677_i2c_probe(struct i2c_client *i2c) static int rt5677_i2c_remove(struct i2c_client *i2c) { - rt5677_free_irq(i2c); rt5677_free_gpio(i2c); return 0; diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index c26edd387e34..45633d8b6a19 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h @@ -1749,6 +1749,7 @@ enum { RT5677_IRQ_JD1, RT5677_IRQ_JD2, RT5677_IRQ_JD3, + RT5677_IRQ_NUM, }; enum rt5677_type { @@ -1827,6 +1828,7 @@ struct rt5677_platform_data { struct rt5677_priv { struct snd_soc_component *component; + struct device *dev; struct rt5677_platform_data pdata; struct regmap *regmap, *regmap_physical; const struct firmware *fw1, *fw2; @@ -1847,9 +1849,13 @@ struct rt5677_priv { struct gpio_chip gpio_chip; #endif bool dsp_vad_en; - struct regmap_irq_chip_data *irq_data; bool is_dsp_mode; bool is_vref_slow; + + /* Interrupt handling */ + struct irq_domain *domain; + struct mutex irq_lock; + unsigned int irq_en; }; int rt5677_sel_asrc_clk_src(struct snd_soc_component *component, From df9091e9d3f4500bc6fb15f5d2a1c2614f67004c Mon Sep 17 00:00:00 2001 From: Ben Zhang Date: Tue, 18 Jun 2019 17:45:55 -0600 Subject: [PATCH 426/626] ASoC: rt5677: handle concurrent interrupts The rt5677 driver writes to the IRQ control register within the IRQ handler in order to flip the polarity of the interrupts that have been signalled. If an interrupt fires in the interval between the regmap_read and the regmap_write, it will not trigger a new call to rt5677_irq. Add a bounded loop to rt5677_irq that keeps checking interrupts until none are seen, so that any interrupts that are signalled in that interval are correctly handled. Signed-off-by: Ben Zhang Signed-off-by: Fletcher Woodruff Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 69 +++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index b5ae61ff87af..202af7135f07 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5072,38 +5072,57 @@ static const struct rt5677_irq_desc rt5677_irq_descs[] = { static irqreturn_t rt5677_irq(int unused, void *data) { struct rt5677_priv *rt5677 = data; - int ret = 0, i, reg_irq, virq; + int ret = 0, loop, i, reg_irq, virq; bool irq_fired = false; mutex_lock(&rt5677->irq_lock); - /* Read interrupt status */ - ret = regmap_read(rt5677->regmap, RT5677_IRQ_CTRL1, ®_irq); - if (ret) { - dev_err(rt5677->dev, "failed reading IRQ status: %d\n", ret); - goto exit; - } - for (i = 0; i < RT5677_IRQ_NUM; i++) { - if (reg_irq & rt5677_irq_descs[i].status_mask) { - irq_fired = true; - virq = irq_find_mapping(rt5677->domain, i); - if (virq) - handle_nested_irq(virq); - - /* Clear the interrupt by flipping the polarity of the - * interrupt source line that fired - */ - reg_irq ^= rt5677_irq_descs[i].polarity_mask; + /* + * Loop to handle interrupts until the last i2c read shows no pending + * irqs. The interrupt line is shared by multiple interrupt sources. + * After the regmap_read() below, a new interrupt source line may + * become high before the regmap_write() finishes, so there isn't a + * rising edge on the shared interrupt line for the new interrupt. Thus, + * the loop is needed to avoid missing irqs. + * + * A safeguard of 20 loops is used to avoid hanging in the irq handler + * if there is something wrong with the interrupt status update. The + * interrupt sources here are audio jack plug/unplug events which + * shouldn't happen at a high frequency for a long period of time. + * Empirically, more than 3 loops have never been seen. + */ + for (loop = 0; loop < 20; loop++) { + /* Read interrupt status */ + ret = regmap_read(rt5677->regmap, RT5677_IRQ_CTRL1, ®_irq); + if (ret) { + dev_err(rt5677->dev, "failed reading IRQ status: %d\n", + ret); + goto exit; } - } - if (!irq_fired) - goto exit; + irq_fired = false; + for (i = 0; i < RT5677_IRQ_NUM; i++) { + if (reg_irq & rt5677_irq_descs[i].status_mask) { + irq_fired = true; + virq = irq_find_mapping(rt5677->domain, i); + if (virq) + handle_nested_irq(virq); - ret = regmap_write(rt5677->regmap, RT5677_IRQ_CTRL1, reg_irq); - if (ret) { - dev_err(rt5677->dev, "failed updating IRQ status: %d\n", ret); - goto exit; + /* Clear the interrupt by flipping the polarity + * of the interrupt source line that fired + */ + reg_irq ^= rt5677_irq_descs[i].polarity_mask; + } + } + if (!irq_fired) + goto exit; + + ret = regmap_write(rt5677->regmap, RT5677_IRQ_CTRL1, reg_irq); + if (ret) { + dev_err(rt5677->dev, "failed updating IRQ status: %d\n", + ret); + goto exit; + } } exit: mutex_unlock(&rt5677->irq_lock); From 1d76898928783d79bfd7c465e891b6cf957c839a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:14:07 +0900 Subject: [PATCH 427/626] ASoC: soc-core: allow no Platform on dai_link dai_link is used to selecting Component (= CPU/Codec/Platform) and DAI (= CPU/Codec). And selected CPU/Codec/Platform components are *listed* on Card. Many drivers don't need special Platform component, but was mandatory at legacy style ALSA SoC. Thus, there is this kind of settings on many drivers. dai_link->platform_of_node = dai_link->cpu_of_node; In this case, soc_bind_dai_link() will pick-up "CPU component" as "Platform component", and try to add it to snd_soc_pcm_runtime. But it will be ignored, because it is already added when CPU bindings. Historically, this kind of "CPU component" is used/selected as "Platform" on many ALSA SoC drivers. OTOH, Dummy Platform will be selected automatically by ALSA SoC if driver doesn't have Platform settings. These indicates that there are 2 type of Platforms exist at current ALSA SoC if driver doesn't need special Platform. 1) use Dummy Platform as Platform component 2) use CPU component as Platform component ALSA SoC will call Dummy Platform callback function if it is using Dummy Platform, but it is completely pointless. Because it is the sound card which doesn't need special Platform. Thus, the behavior we request to ALSA SoC is selecting 2) automatically instead of 1) if sound card doesn't need special Platform. And, 2) means "do nothing" as above explain. These were needed at legacy style dai_link, but is no longer needed at modern style dai_link anymore. This patch allows "no Platform" settings on dai_link, and will do nothing for it if there was no platform settings. This is same as 2). By this patch, all drivers which is selecting "CPU component" as "Platform" can remove such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 2 +- sound/soc/soc-core.c | 64 +++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 80c1ca3a62c7..64405cdab8bb 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -926,7 +926,7 @@ struct snd_soc_dai_link { /* * You MAY specify the link's platform/PCM/DMA driver, either by * device name, or by DT/OF node, but not both. Some forms of link - * do not need a platform. + * do not need a platform. In such case, platforms are not mandatory. */ struct snd_soc_dai_link_component *platforms; unsigned int num_platforms; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f0fa289c90d8..4cd77cd6c864 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -788,6 +788,9 @@ static int snd_soc_is_matching_component( { struct device_node *component_of_node; + if (!dlc) + return 0; + component_of_node = soc_component_to_node(component); if (dlc->of_node && component_of_node != dlc->of_node) @@ -1053,20 +1056,12 @@ static void soc_remove_dai_links(struct snd_soc_card *card) } } -static struct snd_soc_dai_link_component dummy_link = COMP_DUMMY(); - static int soc_init_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) { int i; struct snd_soc_dai_link_component *codec; - /* default Platform */ - if (!link->platforms || !link->num_platforms) { - link->platforms = &dummy_link; - link->num_platforms = 1; - } - for_each_link_codecs(link, i, codec) { /* * Codec must be specified by 1 of name or OF node, @@ -1086,32 +1081,39 @@ static int soc_init_dai_link(struct snd_soc_card *card, } } - /* FIXME */ - if (link->num_platforms > 1) { - dev_err(card->dev, - "ASoC: multi platform is not yet supported %s\n", - link->name); - return -EINVAL; - } - /* - * Platform may be specified by either name or OF node, but - * can be left unspecified, and a dummy platform will be used. + * Platform may be specified by either name or OF node, + * or no Platform. + * + * FIXME + * + * We need multi-platform support */ - if (link->platforms->name && link->platforms->of_node) { - dev_err(card->dev, - "ASoC: Both platform name/of_node are set for %s\n", - link->name); - return -EINVAL; - } + if (link->num_platforms > 0) { - /* - * Defer card registartion if platform dai component is not added to - * component list. - */ - if ((link->platforms->of_node || link->platforms->name) && - !soc_find_component(link->platforms->of_node, link->platforms->name)) - return -EPROBE_DEFER; + if (link->num_platforms > 1) { + dev_err(card->dev, + "ASoC: multi platform is not yet supported %s\n", + link->name); + return -EINVAL; + } + + if (link->platforms->name && link->platforms->of_node) { + dev_err(card->dev, + "ASoC: Both platform name/of_node are set for %s\n", + link->name); + return -EINVAL; + } + + /* + * Defer card registartion if platform dai component is not + * added to component list. + */ + if ((link->platforms->of_node || link->platforms->name) && + !soc_find_component(link->platforms->of_node, + link->platforms->name)) + return -EPROBE_DEFER; + } /* FIXME */ if (link->num_cpus > 1) { From 6c6de1c9e2bf2a0901ca1f2a169d1a2f9fd27958 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:14:12 +0900 Subject: [PATCH 428/626] ASoC: vc4: vc4_hdmi: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 6beac1ca1f27..de05ac8dca12 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -71,7 +71,6 @@ struct vc4_hdmi_audio { struct snd_soc_dai_link link; struct snd_soc_dai_link_component cpu; struct snd_soc_dai_link_component codec; - struct snd_soc_dai_link_component platform; int samplerate; int channels; struct snd_dmaengine_dai_dma_data dma_data; @@ -1101,18 +1100,15 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi) dai_link->cpus = &hdmi->audio.cpu; dai_link->codecs = &hdmi->audio.codec; - dai_link->platforms = &hdmi->audio.platform; dai_link->num_cpus = 1; dai_link->num_codecs = 1; - dai_link->num_platforms = 1; dai_link->name = "MAI"; dai_link->stream_name = "MAI PCM"; dai_link->codecs->dai_name = vc4_hdmi_audio_codec_dai_drv.name; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = dev_name(dev); - dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From 02602401e53168a66d9c5fbf0b16bae0826f8145 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:14:23 +0900 Subject: [PATCH 429/626] ASoC: atmel: atmel-classd: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index cfebbeb92ef1..06111f27b229 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -506,24 +506,21 @@ static int atmel_classd_asoc_card_init(struct device *dev, if (!dai_link) return -ENOMEM; - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; dai_link->cpus = &comp[0]; dai_link->codecs = &comp[1]; - dai_link->platforms = &comp[2]; dai_link->num_cpus = 1; dai_link->num_codecs = 1; - dai_link->num_platforms = 1; dai_link->name = "CLASSD"; dai_link->stream_name = "CLASSD PCM"; dai_link->codecs->dai_name = ATMEL_CLASSD_CODEC_DAI_NAME; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = dev_name(dev); - dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From 7baf32e164da5d447f9525f51fa48665fbf1cd8a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:14:28 +0900 Subject: [PATCH 430/626] ASoC: atmel: atmel-pdmic: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-pdmic.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index f53213402d94..088dd9ff1bcb 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -517,24 +517,21 @@ static int atmel_pdmic_asoc_card_init(struct device *dev, if (!dai_link) return -ENOMEM; - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; dai_link->cpus = &comp[0]; dai_link->codecs = &comp[1]; - dai_link->platforms = &comp[2]; dai_link->num_cpus = 1; dai_link->num_codecs = 1; - dai_link->num_platforms = 1; dai_link->name = "PDMIC"; dai_link->stream_name = "PDMIC PCM"; dai_link->codecs->dai_name = ATMEL_PDMIC_CODEC_DAI_NAME; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = dev_name(dev); - dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From 3609750e9d4ba9db7027866827a0e462fbe86866 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:14:48 +0900 Subject: [PATCH 431/626] ASoC: atmel: atmel_wm8904: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_wm8904.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index 084788ed328c..df5268939331 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c @@ -59,8 +59,7 @@ static const struct snd_soc_ops atmel_asoc_wm8904_ops = { SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8904-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8904-hifi"))); static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { .name = "WM8904", @@ -114,7 +113,6 @@ static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev) return ret; } dailink->cpus->of_node = cpu_np; - dailink->platforms->of_node = cpu_np; of_node_put(cpu_np); codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); From 318ebbe8060d9664370c844029246f0588263fe4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:15:05 +0900 Subject: [PATCH 432/626] ASoC: atmel: mikroe-proto: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/mikroe-proto.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/atmel/mikroe-proto.c b/sound/soc/atmel/mikroe-proto.c index 255168a9df5b..5335ca0ee086 100644 --- a/sound/soc/atmel/mikroe-proto.c +++ b/sound/soc/atmel/mikroe-proto.c @@ -88,8 +88,8 @@ static int snd_proto_probe(struct platform_device *pdev) if (!dai) return -ENOMEM; - /* for cpus/codecs/platforms */ - comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + /* for cpus/codecs */ + comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; @@ -100,8 +100,6 @@ static int snd_proto_probe(struct platform_device *pdev) dai->num_cpus = 1; dai->codecs = &comp[1]; dai->num_codecs = 1; - dai->platforms = &comp[2]; - dai->num_platforms = 1; dai->name = "WM8731"; dai->stream_name = "WM8731 HiFi"; @@ -121,7 +119,6 @@ static int snd_proto_probe(struct platform_device *pdev) return -EINVAL; } dai->cpus->of_node = cpu_np; - dai->platforms->of_node = cpu_np; dai_fmt = snd_soc_of_parse_daifmt(np, NULL, &bitclkmaster, &framemaster); From bfc7938e58142a583a8141f55e453fa1bb68439d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:15:26 +0900 Subject: [PATCH 433/626] ASoC: atmel: sam9g20_wm8731: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/sam9g20_wm8731.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index a5b4c3905ae8..e723153b8437 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -131,8 +131,7 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_CPU("at91rm9200_ssc.0")), - DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("at91rm9200_ssc.0"))); + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi"))); static struct snd_soc_dai_link at91sam9g20ek_dai = { .name = "WM8731", @@ -223,14 +222,12 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev) /* Parse dai and platform info */ at91sam9g20ek_dai.cpus->dai_name = NULL; - at91sam9g20ek_dai.platforms->name = NULL; cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); if (!cpu_np) { dev_err(&pdev->dev, "dai and pcm info missing\n"); return -EINVAL; } at91sam9g20ek_dai.cpus->of_node = cpu_np; - at91sam9g20ek_dai.platforms->of_node = cpu_np; of_node_put(codec_np); of_node_put(cpu_np); From ced5b08020cdd4e2bed194dc35dba504221006ae Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:16:10 +0900 Subject: [PATCH 434/626] ASoC: atmel: sam9x5_wm8731: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/sam9x5_wm8731.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index 36917acc161f..8e8390d6b778 100644 --- a/sound/soc/atmel/sam9x5_wm8731.c +++ b/sound/soc/atmel/sam9x5_wm8731.c @@ -93,7 +93,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); if (!dai || !card || !priv || !comp) { ret = -ENOMEM; goto out; @@ -112,8 +112,6 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) dai->num_cpus = 1; dai->codecs = &comp[1]; dai->num_codecs = 1; - dai->platforms = &comp[2]; - dai->num_platforms = 1; dai->name = "WM8731"; dai->stream_name = "WM8731 PCM"; @@ -150,7 +148,6 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) goto out; } dai->cpus->of_node = cpu_np; - dai->platforms->of_node = cpu_np; priv->ssc_id = of_alias_get_id(cpu_np, "ssc"); From 655368dfc75e86fc69cb8f92260c675c28929bc8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:16:35 +0900 Subject: [PATCH 435/626] ASoC: atmel: tse850-pcm5142: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/tse850-pcm5142.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index 59e2edb22b3a..319acb1676c7 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -296,8 +296,7 @@ static const struct snd_soc_dapm_route tse850_intercon[] = { SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi"))); static struct snd_soc_dai_link tse850_dailink = { .name = "TSE-850", @@ -337,7 +336,6 @@ static int tse850_dt_init(struct platform_device *pdev) return -EINVAL; } dailink->cpus->of_node = cpu_np; - dailink->platforms->of_node = cpu_np; of_node_put(cpu_np); codec_np = of_parse_phandle(np, "axentia,audio-codec", 0); From 2058ea1c4f514a01bc0eba68ffe193d6f39bee43 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:16:42 +0900 Subject: [PATCH 436/626] ASoC: fsl: eukrea-tlv320: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/eukrea-tlv320.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 6f3b768489f6..1ed409d423c3 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -63,8 +63,7 @@ static const struct snd_soc_ops eukrea_tlv320_snd_ops = { SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi"))); static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", @@ -134,10 +133,8 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) ext_port--; eukrea_tlv320_dai.cpus->of_node = ssi_np; - eukrea_tlv320_dai.platforms->of_node = ssi_np; } else { eukrea_tlv320_dai.cpus->dai_name = "imx-ssi.0"; - eukrea_tlv320_dai.platforms->name = "imx-ssi.0"; eukrea_tlv320_dai.codecs->name = "tlv320aic23-codec.0-001a"; eukrea_tlv320.name = "cpuimx-audio"; } From e57a4c2f15df27929303624477b7409405aba0ad Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:16:47 +0900 Subject: [PATCH 437/626] ASoC: fsl: fsl-asoc-card: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 39ea9bda1394..55a7e09170fb 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -201,14 +201,12 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, } SND_SOC_DAILINK_DEFS(hifi, - DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(hifi_fe, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_DUMMY())); SND_SOC_DAILINK_DEFS(hifi_be, DAILINK_COMP_ARRAY(COMP_EMPTY()), @@ -656,14 +654,12 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } } - priv->dai_link[0].platforms->of_node = cpu_np; priv->dai_link[0].dai_fmt = priv->dai_fmt; priv->card.num_links = 1; if (asrc_pdev) { /* DPCM DAI Links only if ASRC exsits */ priv->dai_link[1].cpus->of_node = asrc_np; - priv->dai_link[1].platforms->of_node = asrc_np; priv->dai_link[2].codecs->dai_name = codec_dai_name; priv->dai_link[2].codecs->of_node = codec_np; priv->dai_link[2].codecs->name = From 577cf50d4dc865af13be05d201abbd5a4a4d4be8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:16:51 +0900 Subject: [PATCH 438/626] ASoC: fsl: imx-es8328: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-es8328.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index 15a27a2cd0ca..089ee140c718 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -148,7 +148,7 @@ static int imx_es8328_probe(struct platform_device *pdev) goto fail; } - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) { ret = -ENOMEM; goto fail; @@ -160,18 +160,15 @@ static int imx_es8328_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; - data->dai.num_platforms = 1; data->dai.name = "hifi"; data->dai.stream_name = "hifi"; data->dai.codecs->dai_name = "es8328-hifi-analog"; data->dai.codecs->of_node = codec_np; data->dai.cpus->of_node = ssi_np; - data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_es8328_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; From 82bf78ca49a3a048dcb61620f88d1ae40553ab88 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:16:57 +0900 Subject: [PATCH 439/626] ASoC: fsl: imx-sgtl5000: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-sgtl5000.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 15e8b9343c35..c5ebe4950567 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -123,7 +123,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) goto fail; } - comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) { ret = -ENOMEM; goto fail; @@ -139,18 +139,15 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; - data->dai.num_platforms = 1; data->dai.name = "HiFi"; data->dai.stream_name = "HiFi"; data->dai.codecs->dai_name = "sgtl5000"; data->dai.codecs->of_node = codec_np; data->dai.cpus->of_node = ssi_np; - data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_sgtl5000_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; From 014f07ca1cb12947aea7c9132efe920c5b003b29 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:17:06 +0900 Subject: [PATCH 440/626] ASoC: fsl: imx-spdif: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-spdif.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 6c4dadf60355..393c5a31f494 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,7 +26,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); if (!data || !comp) { ret = -ENOMEM; goto end; @@ -34,18 +34,15 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; - data->dai.num_platforms = 1; data->dai.name = "S/PDIF PCM"; data->dai.stream_name = "S/PDIF PCM"; data->dai.codecs->dai_name = "snd-soc-dummy-dai"; data->dai.codecs->name = "snd-soc-dummy"; data->dai.cpus->of_node = spdif_np; - data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; From d8893261a7d327302520eb9bebb72c5040c2219f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:17:10 +0900 Subject: [PATCH 441/626] ASoC: fsl: imx-audmix: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 9e1cb18859ce..9d41266a5264 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec/Platform x 2 */ - dlc = devm_kzalloc(&pdev->dev, 6 * sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec x 2 */ + dlc = devm_kzalloc(&pdev->dev, 4 * sizeof(*dlc), GFP_KERNEL); if (!dlc) { dev_err(&pdev->dev, "failed to allocate dai_link\n"); return -ENOMEM; @@ -242,11 +242,9 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].cpus = &dlc[0]; priv->dai[i].codecs = &dlc[1]; - priv->dai[i].platforms = &dlc[2]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; - priv->dai[i].num_platforms = 1; priv->dai[i].name = dai_name; priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; @@ -254,7 +252,6 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].codecs->name = "snd-soc-dummy"; priv->dai[i].cpus->of_node = args.np; priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); - priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -269,20 +266,17 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); - priv->dai[num_dai + i].cpus = &dlc[3]; - priv->dai[num_dai + i].codecs = &dlc[4]; - priv->dai[num_dai + i].platforms = &dlc[5]; + priv->dai[num_dai + i].cpus = &dlc[2]; + priv->dai[num_dai + i].codecs = &dlc[3]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; - priv->dai[num_dai + i].num_platforms = 1; priv->dai[num_dai + i].name = be_name; priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; priv->dai[num_dai + i].cpus->of_node = audmix_np; priv->dai[num_dai + i].cpus->dai_name = be_name; - priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; From 717f163317127bc5fdc0d90ad42e3d309dac0df0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:17:14 +0900 Subject: [PATCH 442/626] ASoC: kirkwood: armada-370-db: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/kirkwood/armada-370-db.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c index b2d735b610b8..14f41ea874ef 100644 --- a/sound/soc/kirkwood/armada-370-db.c +++ b/sound/soc/kirkwood/armada-370-db.c @@ -60,18 +60,15 @@ static const struct snd_soc_dapm_route a370db_route[] = { SND_SOC_DAILINK_DEFS(analog, DAILINK_COMP_ARRAY(COMP_CPU("i2s")), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42l51-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42l51-hifi"))); SND_SOC_DAILINK_DEFS(spdif_out, DAILINK_COMP_ARRAY(COMP_CPU("spdif")), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dit-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dit-hifi"))); SND_SOC_DAILINK_DEFS(spdif_in, DAILINK_COMP_ARRAY(COMP_CPU("spdif")), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dir-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dir-hifi"))); static struct snd_soc_dai_link a370db_dai[] = { { @@ -115,21 +112,18 @@ static int a370db_probe(struct platform_device *pdev) a370db_dai[0].cpus->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-controller", 0); - a370db_dai[0].platforms->of_node = a370db_dai[0].cpus->of_node; a370db_dai[0].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-codec", 0); a370db_dai[1].cpus->of_node = a370db_dai[0].cpus->of_node; - a370db_dai[1].platforms->of_node = a370db_dai[0].cpus->of_node; a370db_dai[1].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-codec", 1); a370db_dai[2].cpus->of_node = a370db_dai[0].cpus->of_node; - a370db_dai[2].platforms->of_node = a370db_dai[0].cpus->of_node; a370db_dai[2].codecs->of_node = of_parse_phandle(pdev->dev.of_node, From 5f92229d184b80712a8b94d098318960171ae749 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:17:18 +0900 Subject: [PATCH 443/626] ASoC: mxs: mxs-sgtl5000: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-sgtl5000.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 459fced603b0..088b14a7f8ac 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -78,13 +78,11 @@ static const struct snd_soc_ops mxs_sgtl5000_hifi_ops = { SND_SOC_DAILINK_DEFS(hifi_tx, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000"))); SND_SOC_DAILINK_DEFS(hifi_rx, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000"))); static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { { @@ -139,8 +137,6 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) mxs_sgtl5000_dai[i].codecs->of_node = codec_np; mxs_sgtl5000_dai[i].cpus->dai_name = NULL; mxs_sgtl5000_dai[i].cpus->of_node = saif_np[i]; - mxs_sgtl5000_dai[i].platforms->name = NULL; - mxs_sgtl5000_dai[i].platforms->of_node = saif_np[i]; } of_node_put(codec_np); From 5646843879699a8774c560126b4da4ced97d9b9c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:17:22 +0900 Subject: [PATCH 444/626] ASoC: qcom: apq8016_sbc: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/apq8016_sbc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 717542c61d04..9ac7c9d03ca5 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -159,15 +159,12 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) link = data->dai_link; - dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); + dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL); if (!dlc) return ERR_PTR(-ENOMEM); - link->cpus = &dlc[0]; - link->platforms = &dlc[1]; - - link->num_cpus = 1; - link->num_platforms = 1; + link->cpus = dlc; + link->num_cpus = 1; for_each_child_of_node(node, np) { cpu = of_get_child_by_name(np, "cpu"); @@ -199,7 +196,6 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) goto error; } - link->platforms->of_node = link->cpus->of_node; ret = of_property_read_string(np, "link-name", &link->name); if (ret) { dev_err(card->dev, "error getting codec dai_link name\n"); From 3caf11fa88a954916c14c719b89478f4d89386d5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:17:26 +0900 Subject: [PATCH 445/626] ASoC: qcom: storm: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/storm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c index 672edee2ea93..9c67e42a1f00 100644 --- a/sound/soc/qcom/storm.c +++ b/sound/soc/qcom/storm.c @@ -63,8 +63,7 @@ static const struct snd_soc_ops storm_soc_ops = { SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi"))); static struct snd_soc_dai_link storm_dai_link = { .name = "Primary", @@ -83,7 +82,6 @@ static int storm_parse_of(struct snd_soc_card *card) dev_err(card->dev, "error getting cpu phandle\n"); return -EINVAL; } - dai_link->platforms->of_node = dai_link->cpus->of_node; dai_link->codecs->of_node = of_parse_phandle(np, "codec", 0); if (!dai_link->codecs->of_node) { From 9c21e82c165c009563928f4c0fe21a579352ae5b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:17:51 +0900 Subject: [PATCH 446/626] ASoC: rockchip: rk3288_hdmi_analog: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3288_hdmi_analog.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c index 71ee16d7bde6..7e4bf3323fb1 100644 --- a/sound/soc/rockchip/rk3288_hdmi_analog.c +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c @@ -154,8 +154,7 @@ static const struct snd_soc_ops rk_ops = { SND_SOC_DAILINK_DEFS(audio, DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL), - COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi"))); static struct snd_soc_dai_link rk_dailink = { .name = "Codecs", @@ -249,8 +248,6 @@ static int snd_rk_mc_probe(struct platform_device *pdev) return -EINVAL; } - rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; - ret = snd_soc_of_parse_audio_routing(card, "rockchip,routing"); if (ret) { dev_err(&pdev->dev, From 7df405ae58953a6e880921d1948c33cd357c6ed4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:17:55 +0900 Subject: [PATCH 447/626] ASoC: rockchip: rockchip_max98090: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index fcb5c06a0fe2..6b58f3b97ded 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -125,8 +125,7 @@ static const struct snd_soc_ops rk_aif1_ops = { SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi"))); static struct snd_soc_dai_link rk_dailink = { .name = "max98090", @@ -205,8 +204,6 @@ static int snd_rk_mc_probe(struct platform_device *pdev) return -EINVAL; } - rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; - rk_98090_headset_dev.codec_of_node = of_parse_phandle(np, "rockchip,headset-codec", 0); if (!rk_98090_headset_dev.codec_of_node) { From 27a37973a6f1d508398f6ef1b140e8433870fe8a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:00 +0900 Subject: [PATCH 448/626] ASoC: rockchip: rockchip_rt5645: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_rt5645.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index e17f01635bba..771d3c7305a6 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -137,8 +137,7 @@ static const struct snd_soc_ops rk_aif1_ops = { SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1"))); static struct snd_soc_dai_link rk_dailink = { .name = "rt5645", @@ -190,8 +189,6 @@ static int snd_rk_mc_probe(struct platform_device *pdev) goto put_codec_of_node; } - rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; - ret = snd_soc_of_parse_card_name(card, "rockchip,model"); if (ret) { dev_err(&pdev->dev, From 33949eb5019d4b319e89eb6469a622ebbba30cd5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:04 +0900 Subject: [PATCH 449/626] ASoC: samsung: arndale_rt5631: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/arndale_rt5631.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/samsung/arndale_rt5631.c b/sound/soc/samsung/arndale_rt5631.c index c213913eb984..e36c140400b7 100644 --- a/sound/soc/samsung/arndale_rt5631.c +++ b/sound/soc/samsung/arndale_rt5631.c @@ -52,8 +52,7 @@ static struct snd_soc_ops arndale_ops = { SND_SOC_DAILINK_DEFS(rt5631_hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi"))); static struct snd_soc_dai_link arndale_rt5631_dai[] = { { @@ -93,9 +92,6 @@ static int arndale_audio_probe(struct platform_device *pdev) return -EINVAL; } } - if (!arndale_rt5631_dai[n].platforms->name) - arndale_rt5631_dai[n].platforms->of_node = - arndale_rt5631_dai[n].cpus->of_node; arndale_rt5631_dai[n].codecs->name = NULL; arndale_rt5631_dai[n].codecs->of_node = of_parse_phandle(np, From d815e0f08fdd6259c9fff9eb4dc1834454526e98 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:09 +0900 Subject: [PATCH 450/626] ASoC: samsung: smdk_wm8994: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 28f8be000aa1..99aa1620a17d 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -102,13 +102,11 @@ static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(aif1, DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), - DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1"))); SND_SOC_DAILINK_DEFS(fifo_tx, DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s-sec")), - DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s-sec"))); + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1"))); static struct snd_soc_dai_link smdk_dai[] = { { /* Primary DAI i/f */ @@ -165,9 +163,6 @@ static int smdk_audio_probe(struct platform_device *pdev) "Property 'samsung,i2s-controller' missing or invalid\n"); ret = -EINVAL; } - - smdk_dai[0].platforms->name = NULL; - smdk_dai[0].platforms->of_node = smdk_dai[0].cpus->of_node; } id = of_match_device(of_match_ptr(samsung_wm8994_of_match), &pdev->dev); From a555b6a959e6a1539d8a1dc6a48d5c8920d7724e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:12 +0900 Subject: [PATCH 451/626] ASoC: samsung: snow: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 8ea7799df028..7d669c42cdad 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -14,9 +14,9 @@ #define FIN_PLL_RATE 24000000 -SND_SOC_DAILINK_DEFS(links, - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY()), +SND_SOC_DAILINK_DEF(links_cpus, + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEF(links_codecs, DAILINK_COMP_ARRAY(COMP_EMPTY())); struct snow_priv { @@ -150,8 +150,6 @@ static int snow_probe(struct platform_device *pdev) link->num_cpus = ARRAY_SIZE(links_cpus); link->codecs = links_codecs; link->num_codecs = ARRAY_SIZE(links_codecs); - link->platforms = links_platforms; - link->num_platforms = ARRAY_SIZE(links_platforms); card->dai_link = link; card->num_links = 1; @@ -207,8 +205,6 @@ static int snow_probe(struct platform_device *pdev) } } - link->platforms->of_node = link->cpus->of_node; - /* Update card-name if provided through DT, else use default name */ snd_soc_of_parse_card_name(card, "samsung,model"); From ae7cbcc43b8c275b9f9b2491144110d260cd6b18 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:17 +0900 Subject: [PATCH 452/626] ASoC: samsung: tm2_wm5110: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/tm2_wm5110.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index c091033d17ad..a80781031f62 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -429,21 +429,17 @@ static struct snd_soc_dai_driver tm2_ext_dai[] = { SND_SOC_DAILINK_DEFS(aif1, DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif1")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif1"))); SND_SOC_DAILINK_DEFS(voice, DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif2")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif2"))); SND_SOC_DAILINK_DEFS(bt, DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif3")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif3"))); SND_SOC_DAILINK_DEFS(hdmi, - DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); @@ -576,14 +572,12 @@ static int tm2_probe(struct platform_device *pdev) unsigned int dai_index = 0; /* WM5110 */ dai_link->cpus->name = NULL; - dai_link->platforms->name = NULL; if (num_codecs > 1 && i == card->num_links - 1) dai_index = 1; /* HDMI */ dai_link->codecs->of_node = codec_dai_node[dai_index]; dai_link->cpus->of_node = cpu_dai_node[dai_index]; - dai_link->platforms->of_node = cpu_dai_node[dai_index]; } if (num_codecs > 1) { From e562a5f13c9451e732d13b0a5ad58b6c99ccee8f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:22 +0900 Subject: [PATCH 453/626] ASoC: sirf: sirf-audio: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sirf/sirf-audio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c index ba85ccf1fe19..eb29bca5d18f 100644 --- a/sound/soc/sirf/sirf-audio.c +++ b/sound/soc/sirf/sirf-audio.c @@ -63,8 +63,7 @@ static const struct snd_soc_dapm_route intercon[] = { /* Digital audio interface glue - connects codec <--> CPU */ SND_SOC_DAILINK_DEFS(sirf, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sirf-audio-codec")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sirf-audio-codec"))); static struct snd_soc_dai_link sirf_audio_dai_link[] = { { @@ -99,8 +98,6 @@ static int sirf_audio_probe(struct platform_device *pdev) sirf_audio_dai_link[0].cpus->of_node = of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); - sirf_audio_dai_link[0].platforms->of_node = - of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); sirf_audio_dai_link[0].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0); sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node, From 3f780533bac9025f3e569ebf5ebdc02bd860b27e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:27 +0900 Subject: [PATCH 454/626] ASoC: sunxi: sun4i-codec: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 161444fe4518..a5de4011235f 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1306,24 +1306,21 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, struct snd_soc_dai_link *link = devm_kzalloc(dev, sizeof(*link), GFP_KERNEL); struct snd_soc_dai_link_component *dlc = devm_kzalloc(dev, - 3 * sizeof(*dlc), GFP_KERNEL); + 2 * sizeof(*dlc), GFP_KERNEL); if (!link || !dlc) return NULL; link->cpus = &dlc[0]; link->codecs = &dlc[1]; - link->platforms = &dlc[2]; link->num_cpus = 1; link->num_codecs = 1; - link->num_platforms = 1; link->name = "cdc"; link->stream_name = "CDC PCM"; link->codecs->dai_name = "Codec"; link->cpus->dai_name = dev_name(dev); link->codecs->name = dev_name(dev); - link->platforms->name = dev_name(dev); link->dai_fmt = SND_SOC_DAIFMT_I2S; *num_links = 1; From e7fc99e641da1f0da50328c98e7aa890b49d35d3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:31 +0900 Subject: [PATCH 455/626] ASoC: tegra: tegra_alc5632: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 5a63249ae812..2c1f1311278d 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -126,8 +126,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "alc5632-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "alc5632-hifi"))); static struct snd_soc_dai_link tegra_alc5632_dai = { .name = "ALC5632", @@ -198,8 +197,6 @@ static int tegra_alc5632_probe(struct platform_device *pdev) goto err_put_codec_of_node; } - tegra_alc5632_dai.platforms->of_node = tegra_alc5632_dai.cpus->of_node; - ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev); if (ret) goto err_put_cpu_of_node; @@ -218,7 +215,6 @@ err_fini_utils: err_put_cpu_of_node: of_node_put(tegra_alc5632_dai.cpus->of_node); tegra_alc5632_dai.cpus->of_node = NULL; - tegra_alc5632_dai.platforms->of_node = NULL; err_put_codec_of_node: of_node_put(tegra_alc5632_dai.codecs->of_node); tegra_alc5632_dai.codecs->of_node = NULL; @@ -237,7 +233,6 @@ static int tegra_alc5632_remove(struct platform_device *pdev) of_node_put(tegra_alc5632_dai.cpus->of_node); tegra_alc5632_dai.cpus->of_node = NULL; - tegra_alc5632_dai.platforms->of_node = NULL; of_node_put(tegra_alc5632_dai.codecs->of_node); tegra_alc5632_dai.codecs->of_node = NULL; From 4bfd08540b443ae4e40faf2c385cd9799f5da4d4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:36 +0900 Subject: [PATCH 456/626] ASoC: tegra: tegra_max98090: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_max98090.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index b6c1f4839266..3d5513962952 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c @@ -178,8 +178,7 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi"))); static struct snd_soc_dai_link tegra_max98090_dai = { .name = "max98090", @@ -253,8 +252,6 @@ static int tegra_max98090_probe(struct platform_device *pdev) goto err; } - tegra_max98090_dai.platforms->of_node = tegra_max98090_dai.cpus->of_node; - ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; From 1d641e1523ca401c7e873684b5b65e362c278119 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:40 +0900 Subject: [PATCH 457/626] ASoC: tegra: tegra_rt5640: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_rt5640.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 3f0756132ac4..c6c7ed0f477d 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -128,8 +128,7 @@ static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(aif1, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5640-aif1")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5640-aif1"))); static struct snd_soc_dai_link tegra_rt5640_dai = { .name = "RT5640", @@ -199,8 +198,6 @@ static int tegra_rt5640_probe(struct platform_device *pdev) goto err; } - tegra_rt5640_dai.platforms->of_node = tegra_rt5640_dai.cpus->of_node; - ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; From d035d13b2277ee71babb6a16d31ecdc2f35da189 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:44 +0900 Subject: [PATCH 458/626] ASoC: tegra: tegra_rt5677: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_rt5677.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c index 7edf6c7838f5..db0ea38d3b08 100644 --- a/sound/soc/tegra/tegra_rt5677.c +++ b/sound/soc/tegra/tegra_rt5677.c @@ -171,8 +171,7 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5677-aif1")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5677-aif1"))); static struct snd_soc_dai_link tegra_rt5677_dai = { .name = "RT5677", @@ -271,7 +270,6 @@ static int tegra_rt5677_probe(struct platform_device *pdev) ret = -EINVAL; goto err_put_codec_of_node; } - tegra_rt5677_dai.platforms->of_node = tegra_rt5677_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) @@ -291,7 +289,6 @@ err_fini_utils: err_put_cpu_of_node: of_node_put(tegra_rt5677_dai.cpus->of_node); tegra_rt5677_dai.cpus->of_node = NULL; - tegra_rt5677_dai.platforms->of_node = NULL; err_put_codec_of_node: of_node_put(tegra_rt5677_dai.codecs->of_node); tegra_rt5677_dai.codecs->of_node = NULL; @@ -308,7 +305,6 @@ static int tegra_rt5677_remove(struct platform_device *pdev) tegra_asoc_utils_fini(&machine->util_data); - tegra_rt5677_dai.platforms->of_node = NULL; of_node_put(tegra_rt5677_dai.codecs->of_node); tegra_rt5677_dai.codecs->of_node = NULL; of_node_put(tegra_rt5677_dai.cpus->of_node); From cee1cf3f9f9ed7b5fecfcd194cbb7e3718d8da5f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:48 +0900 Subject: [PATCH 459/626] ASoC: tegra: tegra_sgtl5000: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_sgtl5000.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c index c5d45a6147bd..2a9e1ceaa574 100644 --- a/sound/soc/tegra/tegra_sgtl5000.c +++ b/sound/soc/tegra/tegra_sgtl5000.c @@ -94,8 +94,7 @@ static const struct snd_soc_dapm_widget tegra_sgtl5000_dapm_widgets[] = { SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000"))); static struct snd_soc_dai_link tegra_sgtl5000_dai = { .name = "sgtl5000", @@ -157,8 +156,6 @@ static int tegra_sgtl5000_driver_probe(struct platform_device *pdev) goto err_put_codec_of_node; } - tegra_sgtl5000_dai.platforms->of_node = tegra_sgtl5000_dai.cpus->of_node; - ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err_put_cpu_of_node; @@ -177,7 +174,6 @@ err_fini_utils: err_put_cpu_of_node: of_node_put(tegra_sgtl5000_dai.cpus->of_node); tegra_sgtl5000_dai.cpus->of_node = NULL; - tegra_sgtl5000_dai.platforms->of_node = NULL; err_put_codec_of_node: of_node_put(tegra_sgtl5000_dai.codecs->of_node); tegra_sgtl5000_dai.codecs->of_node = NULL; @@ -197,7 +193,6 @@ static int tegra_sgtl5000_driver_remove(struct platform_device *pdev) of_node_put(tegra_sgtl5000_dai.cpus->of_node); tegra_sgtl5000_dai.cpus->of_node = NULL; - tegra_sgtl5000_dai.platforms->of_node = NULL; of_node_put(tegra_sgtl5000_dai.codecs->of_node); tegra_sgtl5000_dai.codecs->of_node = NULL; From 404b229b84afa2ffba14ea83e52d1434d7698520 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:51 +0900 Subject: [PATCH 460/626] ASoC: tegra: tegra_wm8753: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8753.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 8492b3dbb788..bbefad5ec400 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -100,8 +100,7 @@ static const struct snd_soc_dapm_widget tegra_wm8753_dapm_widgets[] = { SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8753-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8753-hifi"))); static struct snd_soc_dai_link tegra_wm8753_dai = { .name = "WM8753", @@ -165,8 +164,6 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev) goto err; } - tegra_wm8753_dai.platforms->of_node = tegra_wm8753_dai.cpus->of_node; - ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; From b28d985271578efa4eaefba92f22182820b23930 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:18:55 +0900 Subject: [PATCH 461/626] ASoC: tegra: tegra_wm8903: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 5915bf4cf496..8a802371f3b7 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -211,8 +211,7 @@ static int tegra_wm8903_remove(struct snd_soc_card *card) SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8903-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8903-hifi"))); static struct snd_soc_dai_link tegra_wm8903_dai = { .name = "WM8903", @@ -339,8 +338,6 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev) goto err; } - tegra_wm8903_dai.platforms->of_node = tegra_wm8903_dai.cpus->of_node; - ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; From 5d62677238e94c0c347b386c3d9787b17d92a4c8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:00 +0900 Subject: [PATCH 462/626] ASoC: tegra: tegra_wm9712: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm9712.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c index 7526aee3a0e3..cac8496697ed 100644 --- a/sound/soc/tegra/tegra_wm9712.c +++ b/sound/soc/tegra/tegra_wm9712.c @@ -51,8 +51,7 @@ static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi"))); static struct snd_soc_dai_link tegra_wm9712_dai = { .name = "AC97 HiFi", @@ -114,8 +113,6 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev) goto codec_unregister; } - tegra_wm9712_dai.platforms->of_node = tegra_wm9712_dai.cpus->of_node; - ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto codec_unregister; From 567b374d99733ff4bee751636bb3d34e81c6a7e8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:04 +0900 Subject: [PATCH 463/626] ASoC: tegra: trimslice: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/trimslice.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index a553daa34e87..5ec8f943be81 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -93,8 +93,7 @@ static const struct snd_soc_dapm_route trimslice_audio_map[] = { SND_SOC_DAILINK_DEFS(single_dsp, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi"))); static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { .name = "TLV320AIC23", @@ -152,9 +151,6 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev) goto err; } - trimslice_tlv320aic23_dai.platforms->of_node = - trimslice_tlv320aic23_dai.cpus->of_node; - ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); if (ret) goto err; From f46da1b9046ed80748a58e9b3c701fb7297a50e2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:08 +0900 Subject: [PATCH 464/626] ASoC: ti: davinci-evm: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/davinci-evm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c index bd822bc8040f..d920befc3e10 100644 --- a/sound/soc/ti/davinci-evm.c +++ b/sound/soc/ti/davinci-evm.c @@ -356,8 +356,7 @@ static struct snd_soc_card da850_snd_soc_card = { */ SND_SOC_DAILINK_DEFS(evm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic3x-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic3x-hifi"))); static struct snd_soc_dai_link evm_dai_tlv320aic3x = { .name = "TLV320AIC3X", @@ -411,8 +410,6 @@ static int davinci_evm_probe(struct platform_device *pdev) if (!dai->cpus->of_node) return -EINVAL; - dai->platforms->of_node = dai->cpus->of_node; - evm_soc_card.dev = &pdev->dev; ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model"); if (ret) From 1306ab2eddd1ede09da7a849ef92c3c820d6850e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:11 +0900 Subject: [PATCH 465/626] ASoC: ti: omap-abe-twl6040: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-abe-twl6040.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c index 3522ea7aa8d9..475a074600f6 100644 --- a/sound/soc/ti/omap-abe-twl6040.c +++ b/sound/soc/ti/omap-abe-twl6040.c @@ -35,17 +35,17 @@ #include "omap-mcpdm.h" #include "../codecs/twl6040.h" -SND_SOC_DAILINK_DEFS(link0, - DAILINK_COMP_ARRAY(COMP_EMPTY()), +SND_SOC_DAILINK_DEF(link0_cpus, + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEF(link0_codecs, DAILINK_COMP_ARRAY(COMP_CODEC("twl6040-codec", - "twl6040-legacy")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + "twl6040-legacy"))); -SND_SOC_DAILINK_DEFS(link1, - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", - "dmic-hifi")), +SND_SOC_DAILINK_DEF(link1_cpus, DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEF(link1_codecs, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", + "dmic-hifi"))); struct abe_twl6040 { struct snd_soc_card card; @@ -270,9 +270,6 @@ static int omap_abe_probe(struct platform_device *pdev) priv->dai_links[0].cpus = link0_cpus; priv->dai_links[0].num_cpus = 1; priv->dai_links[0].cpus->of_node = dai_node; - priv->dai_links[0].platforms = link0_platforms; - priv->dai_links[0].num_platforms = 1; - priv->dai_links[0].platforms->of_node = dai_node; priv->dai_links[0].codecs = link0_codecs; priv->dai_links[0].num_codecs = 1; priv->dai_links[0].init = omap_abe_twl6040_init; @@ -286,9 +283,6 @@ static int omap_abe_probe(struct platform_device *pdev) priv->dai_links[1].cpus = link1_cpus; priv->dai_links[1].num_cpus = 1; priv->dai_links[1].cpus->of_node = dai_node; - priv->dai_links[1].platforms = link1_platforms; - priv->dai_links[1].num_platforms = 1; - priv->dai_links[1].platforms->of_node = dai_node; priv->dai_links[1].codecs = link1_codecs; priv->dai_links[1].num_codecs = 1; priv->dai_links[1].init = omap_abe_dmic_init; From edba13aeae88feda7b689bccbbcdc911377a3fdd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:14 +0900 Subject: [PATCH 466/626] ASoC: ti: omap-hdmi: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-hdmi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index 11c1440da226..58207ba3b02a 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -373,20 +373,17 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) if (!card->dai_link) return -ENOMEM; - compnent = devm_kzalloc(dev, 3 * sizeof(*compnent), GFP_KERNEL); + compnent = devm_kzalloc(dev, 2 * sizeof(*compnent), GFP_KERNEL); if (!compnent) return -ENOMEM; card->dai_link->cpus = &compnent[0]; card->dai_link->num_cpus = 1; card->dai_link->codecs = &compnent[1]; card->dai_link->num_codecs = 1; - card->dai_link->platforms = &compnent[2]; - card->dai_link->num_platforms = 1; card->dai_link->name = card->name; card->dai_link->stream_name = card->name; card->dai_link->cpus->dai_name = dev_name(ad->dssdev); - card->dai_link->platforms->name = dev_name(ad->dssdev); card->dai_link->codecs->name = "snd-soc-dummy"; card->dai_link->codecs->dai_name = "snd-soc-dummy-dai"; card->num_links = 1; From bfe1273c65e1c97ed3861fecd4812f2feeb67800 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:18 +0900 Subject: [PATCH 467/626] ASoC: ti: omap-twl4030: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-twl4030.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/sound/soc/ti/omap-twl4030.c b/sound/soc/ti/omap-twl4030.c index ddd24b2809b8..266999804cfd 100644 --- a/sound/soc/ti/omap-twl4030.c +++ b/sound/soc/ti/omap-twl4030.c @@ -211,13 +211,11 @@ static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) /* Digital audio interface glue - connects codec <--> CPU */ SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.2")), - DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.2"))); + DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-hifi"))); SND_SOC_DAILINK_DEFS(voice, DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.3")), - DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-voice")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.3"))); + DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-voice"))); static struct snd_soc_dai_link omap_twl4030_dai_links[] = { { @@ -279,18 +277,12 @@ static int omap_twl4030_probe(struct platform_device *pdev) omap_twl4030_dai_links[0].cpus->dai_name = NULL; omap_twl4030_dai_links[0].cpus->of_node = dai_node; - omap_twl4030_dai_links[0].platforms->name = NULL; - omap_twl4030_dai_links[0].platforms->of_node = dai_node; - dai_node = of_parse_phandle(node, "ti,mcbsp-voice", 0); if (!dai_node) { card->num_links = 1; } else { omap_twl4030_dai_links[1].cpus->dai_name = NULL; omap_twl4030_dai_links[1].cpus->of_node = dai_node; - - omap_twl4030_dai_links[1].platforms->name = NULL; - omap_twl4030_dai_links[1].platforms->of_node = dai_node; } priv->jack_detect = of_get_named_gpio(node, From f0edc6c1ee48c947d762b0e21b8d3f61858f47f0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:24 +0900 Subject: [PATCH 468/626] ASoC: ti: rx51: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/rx51.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index 0684f961de76..dff751c45b52 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -315,8 +315,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(aic34, DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.2")), DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.2-0018", - "tlv320aic3x-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.2"))); + "tlv320aic3x-hifi"))); static struct snd_soc_dai_link rx51_dai[] = { { @@ -393,9 +392,7 @@ static int rx51_soc_probe(struct platform_device *pdev) return -EINVAL; } rx51_dai[0].cpus->dai_name = NULL; - rx51_dai[0].platforms->name = NULL; rx51_dai[0].cpus->of_node = dai_node; - rx51_dai[0].platforms->of_node = dai_node; dai_node = of_parse_phandle(np, "nokia,audio-codec", 0); if (!dai_node) { From 9ae6cdb184b651bf48b9feed4f947468ff1c3c1f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:28 +0900 Subject: [PATCH 469/626] ASoC: ux500: mop500: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ux500/mop500.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 20552e9d9217..12b2260efaf4 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -29,13 +29,11 @@ /* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ SND_SOC_DAILINK_DEFS(link1, DAILINK_COMP_ARRAY(COMP_CPU("ux500-msp-i2s.1")), - DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.0")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("ux500-msp-i2s.1"))); + DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.0"))); SND_SOC_DAILINK_DEFS(link2, DAILINK_COMP_ARRAY(COMP_CPU("ux500-msp-i2s.3")), - DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.1")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("ux500-msp-i2s.3"))); + DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.1"))); static struct snd_soc_dai_link mop500_dai_links[] = { { @@ -91,8 +89,6 @@ static int mop500_of_probe(struct platform_device *pdev, for (i = 0; i < 2; i++) { mop500_dai_links[i].cpus->of_node = msp_np[i]; mop500_dai_links[i].cpus->dai_name = NULL; - mop500_dai_links[i].platforms->of_node = msp_np[i]; - mop500_dai_links[i].platforms->name = NULL; mop500_dai_links[i].codecs->of_node = codec_np; mop500_dai_links[i].codecs->name = NULL; } From 6f043744573520095bdee9e532d75574060e62f4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:31 +0900 Subject: [PATCH 470/626] ASoC: simple-card-utils: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index ac8678fe55ff..3cf5cb21ea52 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -346,9 +346,18 @@ EXPORT_SYMBOL_GPL(asoc_simple_dai_init); void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link) { - /* Assumes platform == cpu */ - if (!dai_link->platforms->of_node) - dai_link->platforms->of_node = dai_link->cpus->of_node; + /* + * no Platform + * + * It will be waste of memory, but not be memory leak. + * see + * asoc_simple_init_priv() + * asoc_simple_priv + */ + if (!dai_link->platforms->of_node) { + dai_link->platforms = NULL; + dai_link->num_platforms = 0; + } } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); From 0814c6412967bac140ef9878ad48e1f30e5afba3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:35 +0900 Subject: [PATCH 471/626] ASoC: qcom: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 97488b5cc515..adf49b198754 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -103,7 +103,9 @@ int qcom_snd_parse_of(struct snd_soc_card *card) link->codecs = dlc; link->num_codecs = 1; - link->platforms->of_node = link->cpus->of_node; + link->platforms = NULL; + link->num_platforms = 0; + link->codecs->dai_name = "snd-soc-dummy-dai"; link->codecs->name = "snd-soc-dummy"; link->dynamic = 1; From 961fb3c206dc84febe87cc433ca321eb6587ec66 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:40 +0900 Subject: [PATCH 472/626] ASoC: rockchip: rk3399_gru_sound: don't select unnecessary Platform ALSA SoC is now supporting "no Platform". Sound card doesn't need to select "CPU component" as "Platform" anymore if it doesn't need special Platform. This patch removes such settings. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3399_gru_sound.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 5e2700283fa8..879069fc0b94 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -278,33 +278,27 @@ enum { SND_SOC_DAILINK_DEFS(cdndp, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi"))); SND_SOC_DAILINK_DEFS(da7219, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi"))); SND_SOC_DAILINK_DEFS(dmic, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi"))); SND_SOC_DAILINK_DEFS(max98357a, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi"))); SND_SOC_DAILINK_DEFS(rt5514, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1"))); SND_SOC_DAILINK_DEFS(rt5514_dsp, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_DUMMY())); static const struct snd_soc_dai_link rockchip_dais[] = { [DAILINK_CDNDP] = { @@ -538,7 +532,6 @@ static int rockchip_sound_of_parse_dais(struct device *dev, if (!dai->codecs->name) dai->codecs->of_node = np_codec; - dai->platforms->of_node = np_cpu; dai->cpus->of_node = np_cpu; if (card->num_dapm_routes + rockchip_routes[index].num_routes > From 64ee5067cf64f948449201579d89829b5c693c16 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:19:44 +0900 Subject: [PATCH 473/626] ASoC: soc-utils: remove dummy Platform ALSA SoC used 2 type of Platform if sound card doesn't need Platform. 1) use Dummy Platform as Platform component 2) use CPU component as Platform component Now, ALSA SoC allows "no Platform" settings, and it will behave same as 2) case selection. And, all sound card which doesn't need specific Platform are now not selecting Platform any more. This means, no sound card is using dummy Platform on ALSA SoC any more. This patch removes unused dummy Platform. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-utils.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index e3b9dd634c6d..f67e715a9f42 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -262,26 +262,6 @@ static const struct snd_pcm_hardware dummy_dma_hardware = { .periods_max = 128, }; -static int dummy_dma_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - - /* BE's dont need dummy params */ - if (!rtd->dai_link->no_pcm) - snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware); - - return 0; -} - -static const struct snd_pcm_ops snd_dummy_dma_ops = { - .open = dummy_dma_open, - .ioctl = snd_pcm_lib_ioctl, -}; - -static const struct snd_soc_component_driver dummy_platform = { - .ops = &snd_dummy_dma_ops, -}; - static const struct snd_soc_component_driver dummy_codec = { .idle_bias_on = 1, .use_pmdown_time = 1, @@ -339,11 +319,6 @@ static int snd_soc_dummy_probe(struct platform_device *pdev) ret = devm_snd_soc_register_component(&pdev->dev, &dummy_codec, &dummy_dai, 1); - if (ret < 0) - return ret; - - ret = devm_snd_soc_register_component(&pdev->dev, &dummy_platform, - NULL, 0); return ret; } From 1e7f6e1c69f0ff35c90878f9b44adcff77995eb9 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 19 Jun 2019 13:40:02 +0200 Subject: [PATCH 474/626] ASoC: stm32: dfsdm: add 16 bits audio record support Add support of audio 16 bits format record to STM32 DFSDM driver. Signed-off-by: Olivier Moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_adfsdm.c | 49 ++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index cc517e007039..3c9a9deec9af 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -45,7 +45,7 @@ struct stm32_adfsdm_priv { static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_PAUSE, - .formats = SNDRV_PCM_FMTBIT_S32_LE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .rate_min = 8000, .rate_max = 32000, @@ -141,7 +141,8 @@ static const struct snd_soc_dai_driver stm32_adfsdm_dai = { .capture = { .channels_min = 1, .channels_max = 1, - .formats = SNDRV_PCM_FMTBIT_S32_LE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000), }, @@ -152,30 +153,58 @@ static const struct snd_soc_component_driver stm32_adfsdm_dai_component = { .name = "stm32_dfsdm_audio", }; +static void memcpy_32to16(void *dest, const void *src, size_t n) +{ + unsigned int i = 0; + u16 *d = (u16 *)dest, *s = (u16 *)src; + + s++; + for (i = n; i > 0; i--) { + *d++ = *s++; + s++; + } +} + static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) { struct stm32_adfsdm_priv *priv = private; struct snd_soc_pcm_runtime *rtd = priv->substream->private_data; u8 *pcm_buff = priv->pcm_buff; u8 *src_buff = (u8 *)data; - unsigned int buff_size = snd_pcm_lib_buffer_bytes(priv->substream); - unsigned int period_size = snd_pcm_lib_period_bytes(priv->substream); unsigned int old_pos = priv->pos; - unsigned int cur_size = size; + size_t buff_size = snd_pcm_lib_buffer_bytes(priv->substream); + size_t period_size = snd_pcm_lib_period_bytes(priv->substream); + size_t cur_size, src_size = size; + snd_pcm_format_t format = priv->substream->runtime->format; + + if (format == SNDRV_PCM_FORMAT_S16_LE) + src_size >>= 1; + cur_size = src_size; dev_dbg(rtd->dev, "%s: buff_add :%pK, pos = %d, size = %zu\n", - __func__, &pcm_buff[priv->pos], priv->pos, size); + __func__, &pcm_buff[priv->pos], priv->pos, src_size); - if ((priv->pos + size) > buff_size) { - memcpy(&pcm_buff[priv->pos], src_buff, buff_size - priv->pos); + if ((priv->pos + src_size) > buff_size) { + if (format == SNDRV_PCM_FORMAT_S16_LE) + memcpy_32to16(&pcm_buff[priv->pos], src_buff, + buff_size - priv->pos); + else + memcpy(&pcm_buff[priv->pos], src_buff, + buff_size - priv->pos); cur_size -= buff_size - priv->pos; priv->pos = 0; } - memcpy(&pcm_buff[priv->pos], &src_buff[size - cur_size], cur_size); + if (format == SNDRV_PCM_FORMAT_S16_LE) + memcpy_32to16(&pcm_buff[priv->pos], + &src_buff[src_size - cur_size], cur_size); + else + memcpy(&pcm_buff[priv->pos], &src_buff[src_size - cur_size], + cur_size); + priv->pos = (priv->pos + cur_size) % buff_size; - if (cur_size != size || (old_pos && (old_pos % period_size < size))) + if (cur_size != src_size || (old_pos && (old_pos % period_size < size))) snd_pcm_period_elapsed(priv->substream); return 0; From f0b1f5f08dfbc043fb3759a3ed6d0a249d55e8ec Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 19 Jun 2019 14:41:55 +0100 Subject: [PATCH 475/626] ASoC: madera: Add DT bindings for Cirrus Logic Madera codecs The Cirrus Logic Madera codecs are a family of related codecs with extensive digital and analogue I/O, digital mixing and routing, signal processing and programmable DSPs. Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/madera.txt | 67 +++++++++++++++++++ MAINTAINERS | 1 + include/dt-bindings/sound/madera.h | 29 ++++++++ 3 files changed, 97 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/madera.txt create mode 100644 include/dt-bindings/sound/madera.h diff --git a/Documentation/devicetree/bindings/sound/madera.txt b/Documentation/devicetree/bindings/sound/madera.txt new file mode 100644 index 000000000000..5e669ce552f4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/madera.txt @@ -0,0 +1,67 @@ +Cirrus Logic Madera class audio codecs + +This describes audio configuration bindings for these codecs. + +See also the core bindings for the parent MFD driver: +See Documentation/devicetree/bindings/mfd/madera.txt + +and defines for values used in these bindings: +include/dt-bindings/sound/madera.h + +These properties are all contained in the parent MFD node. + +Optional properties: + - cirrus,dmic-ref : Indicates how the MICBIAS pins have been externally + connected to DMICs on each input, one cell per input. + + A value of 0 indicates MICVDD and is the default, other values depend on the + codec: + For CS47L35 one of the CS47L35_DMIC_REF_xxx values + For all other codecs one of the MADERA_DMIC_REF_xxx values + Also see the datasheet for a description of the INn_DMIC_SUP field. + + - cirrus,inmode : A list of input mode settings for each input. A maximum of + 16 cells, with four cells per input in the order INnAL, INnAR INnBL INnBR. + For non-muxed inputs the first two cells for that input set the mode for + the left and right channel and the second two cells must be 0. + For muxed inputs the first two cells for that input set the mode of the + left and right A inputs and the second two cells set the mode of the left + and right B inputs. + Valid mode values are one of the MADERA_INMODE_xxx. If the array is shorter + than the number of inputs the unspecified inputs default to + MADERA_INMODE_DIFF. + + - cirrus,out-mono : Mono bit for each output, maximum of six cells if the + array is shorter outputs will be set to stereo. + + - cirrus,max-channels-clocked : Maximum number of channels that I2S clocks + will be generated for. Useful when clock master for systems where the I2S + bus has multiple data lines. + One cell for each AIF, use a value of zero for AIFs that should be handled + normally. + + - cirrus,pdm-fmt : PDM speaker data format, must contain 2 cells + (OUT5 and OUT6). See the PDM_SPKn_FMT field in the datasheet for a + description of this value. + The second cell is ignored for codecs that do not have OUT6. + + - cirrus,pdm-mute : PDM mute format, must contain 2 cells + (OUT5 and OUT6). See the PDM_SPKn_CTRL_1 register in the datasheet for a + description of this value. + The second cell is ignored for codecs that do not have OUT6. + +Example: + +cs47l35@0 { + compatible = "cirrus,cs47l35"; + + cirrus,dmic-ref = <0 0 CS47L35_DMIC_REF_MICBIAS1B 0>; + cirrus,inmode = < + MADERA_INMODE_DMIC MADERA_INMODE_DMIC /* IN1A digital */ + MADERA_INMODE_SE MADERA_INMODE_SE /* IN1B single-ended */ + MADERA_INMODE_DIFF MADERA_INMODE_DIFF /* IN2 differential */ + 0 0 /* not used on this codec */ + >; + cirrus,out-mono = <0 0 0 0 0 0>; + cirrus,max-channels-clocked = <2 0 0>; +}; diff --git a/MAINTAINERS b/MAINTAINERS index b3d686fba562..c35d1f72bc73 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3915,6 +3915,7 @@ W: https://github.com/CirrusLogic/linux-drivers/wiki S: Supported F: Documentation/devicetree/bindings/mfd/madera.txt F: Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt +F: include/dt-bindings/sound/madera* F: include/linux/irqchip/irq-madera* F: include/linux/mfd/madera/* F: drivers/gpio/gpio-madera* diff --git a/include/dt-bindings/sound/madera.h b/include/dt-bindings/sound/madera.h new file mode 100644 index 000000000000..9ff4eae5259b --- /dev/null +++ b/include/dt-bindings/sound/madera.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Device Tree defines for Madera codecs + * + * Copyright (C) 2016-2017 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef DT_BINDINGS_SOUND_MADERA_H +#define DT_BINDINGS_SOUND_MADERA_H + +#define MADERA_INMODE_DIFF 0 +#define MADERA_INMODE_SE 1 +#define MADERA_INMODE_DMIC 2 + +#define MADERA_DMIC_REF_MICVDD 0 +#define MADERA_DMIC_REF_MICBIAS1 1 +#define MADERA_DMIC_REF_MICBIAS2 2 +#define MADERA_DMIC_REF_MICBIAS3 3 + +#define CS47L35_DMIC_REF_MICBIAS1B 1 +#define CS47L35_DMIC_REF_MICBIAS2A 2 +#define CS47L35_DMIC_REF_MICBIAS2B 3 + +#endif From 2735b683e1f284560f7e8e1d1ebf385ab111312d Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 19 Jun 2019 14:41:56 +0100 Subject: [PATCH 476/626] ASoC: madera: Add common support for Cirrus Logic Madera codecs The Cirrus Logic Madera codecs are a family of related codecs with extensive digital and analogue I/O, digital mixing and routing, signal processing and programmable DSPs. This patch adds common support code shared by all Madera codecs. This patch also adds the pdata to the parent mfd pdata struct. Since there is a circular build dependency it's convenient to patch them both atomically. Signed-off-by: Nariman Poushin Signed-off-by: Nikesh Oswal Signed-off-by: Piotr Stankiewicz Signed-off-by: Ajit Pandey Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- MAINTAINERS | 4 + include/linux/mfd/madera/pdata.h | 4 + include/sound/madera-pdata.h | 63 + sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/madera.c | 4181 ++++++++++++++++++++++++++++++ sound/soc/codecs/madera.h | 446 ++++ 7 files changed, 4705 insertions(+) create mode 100644 include/sound/madera-pdata.h create mode 100644 sound/soc/codecs/madera.c create mode 100644 sound/soc/codecs/madera.h diff --git a/MAINTAINERS b/MAINTAINERS index c35d1f72bc73..9ea100957c59 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3915,14 +3915,18 @@ W: https://github.com/CirrusLogic/linux-drivers/wiki S: Supported F: Documentation/devicetree/bindings/mfd/madera.txt F: Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt +F: Documentation/devicetree/bindings/sound/madera.txt F: include/dt-bindings/sound/madera* F: include/linux/irqchip/irq-madera* F: include/linux/mfd/madera/* +F: include/sound/madera* F: drivers/gpio/gpio-madera* F: drivers/irqchip/irq-madera* F: drivers/mfd/madera* F: drivers/mfd/cs47l* F: drivers/pinctrl/cirrus/* +F: sound/soc/codecs/cs47l* +F: sound/soc/codecs/madera* CLANG-FORMAT FILE M: Miguel Ojeda diff --git a/include/linux/mfd/madera/pdata.h b/include/linux/mfd/madera/pdata.h index 8dc852402dbb..60cd8ec98563 100644 --- a/include/linux/mfd/madera/pdata.h +++ b/include/linux/mfd/madera/pdata.h @@ -16,6 +16,7 @@ #include #include #include +#include #define MADERA_MAX_MICBIAS 4 #define MADERA_MAX_CHILD_MICBIAS 4 @@ -39,6 +40,7 @@ struct madera_codec_pdata; * @gpsw: General purpose switch mode setting. Depends on the external * hardware connected to the switch. (See the SW1_MODE field * in the datasheet for the available values for your codec) + * @codec: Substruct of pdata for the ASoC codec driver */ struct madera_pdata { struct gpio_desc *reset; @@ -53,6 +55,8 @@ struct madera_pdata { int n_gpio_configs; u32 gpsw[MADERA_MAX_GPSW]; + + struct madera_codec_pdata codec; }; #endif diff --git a/include/sound/madera-pdata.h b/include/sound/madera-pdata.h new file mode 100644 index 000000000000..441decefb7f3 --- /dev/null +++ b/include/sound/madera-pdata.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Platform data for Madera codec driver + * + * Copyright (C) 2016-2019 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef MADERA_CODEC_PDATA_H +#define MADERA_CODEC_PDATA_H + +#include + +#define MADERA_MAX_INPUT 6 +#define MADERA_MAX_MUXED_CHANNELS 4 +#define MADERA_MAX_OUTPUT 6 +#define MADERA_MAX_AIF 4 +#define MADERA_MAX_PDM_SPK 2 +#define MADERA_MAX_DSP 7 + +/** + * struct madera_codec_pdata + * + * @max_channels_clocked: Maximum number of channels that I2S clocks will be + * generated for. Useful when clock master for systems + * where the I2S bus has multiple data lines. + * @dmic_ref: Indicates how the MICBIAS pins have been externally + * connected to DMICs on each input. A value of 0 + * indicates MICVDD and is the default. Other values are: + * For CS47L35 one of the CS47L35_DMIC_REF_xxx values + * For all other codecs one of the MADERA_DMIC_REF_xxx + * Also see the datasheet for a description of the + * INn_DMIC_SUP field. + * @inmode: Mode for the ADC inputs. One of the MADERA_INMODE_xxx + * values. Two-dimensional array + * [input_number][channel number], with four slots per + * input in the order + * [n][0]=INnAL [n][1]=INnAR [n][2]=INnBL [n][3]=INnBR + * @out_mono: For each output set the value to TRUE to indicate that + * the output is mono. [0]=OUT1, [1]=OUT2, ... + * @pdm_fmt: PDM speaker data format. See the PDM_SPKn_FMT field in + * the datasheet for a description of this value. + * @pdm_mute: PDM mute format. See the PDM_SPKn_CTRL_1 register + * in the datasheet for a description of this value. + */ +struct madera_codec_pdata { + u32 max_channels_clocked[MADERA_MAX_AIF]; + + u32 dmic_ref[MADERA_MAX_INPUT]; + + u32 inmode[MADERA_MAX_INPUT][MADERA_MAX_MUXED_CHANNELS]; + + bool out_mono[MADERA_MAX_OUTPUT]; + + u32 pdm_fmt[MADERA_MAX_PDM_SPK]; + u32 pdm_mute[MADERA_MAX_PDM_SPK]; +}; + +#endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1bda52ef0cd0..f3ac661b8845 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -284,10 +284,12 @@ config SND_SOC_WM_HUBS config SND_SOC_WM_ADSP tristate select SND_SOC_COMPRESS + default y if SND_SOC_MADERA=y default y if SND_SOC_CS47L24=y default y if SND_SOC_WM5102=y default y if SND_SOC_WM5110=y default y if SND_SOC_WM2200=y + default m if SND_SOC_MADERA=m default m if SND_SOC_CS47L24=m default m if SND_SOC_WM5102=m default m if SND_SOC_WM5110=m @@ -704,6 +706,9 @@ config SND_SOC_LOCHNAGAR_SC This driver support the sound card functionality of the Cirrus Logic Lochnagar audio development board. +config SND_SOC_MADERA + tristate + config SND_SOC_MAX98088 tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 112701fd44a8..d21e1be3e7a7 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -93,6 +93,7 @@ snd-soc-l3-objs := l3.o snd-soc-lm4857-objs := lm4857.o snd-soc-lm49453-objs := lm49453.o snd-soc-lochnagar-sc-objs := lochnagar-sc.o +snd-soc-madera-objs := madera.o snd-soc-max9759-objs := max9759.o snd-soc-max9768-objs := max9768.o snd-soc-max98088-objs := max98088.o @@ -369,6 +370,7 @@ obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o obj-$(CONFIG_SND_SOC_LOCHNAGAR_SC) += snd-soc-lochnagar-sc.o +obj-$(CONFIG_SND_SOC_MADERA) += snd-soc-madera.o obj-$(CONFIG_SND_SOC_MAX9759) += snd-soc-max9759.o obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c new file mode 100644 index 000000000000..6146c7a070cb --- /dev/null +++ b/sound/soc/codecs/madera.c @@ -0,0 +1,4181 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Cirrus Logic Madera class codecs common support +// +// Copyright (C) 2015-2019 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by the +// Free Software Foundation; version 2. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "madera.h" + +#define MADERA_AIF_BCLK_CTRL 0x00 +#define MADERA_AIF_TX_PIN_CTRL 0x01 +#define MADERA_AIF_RX_PIN_CTRL 0x02 +#define MADERA_AIF_RATE_CTRL 0x03 +#define MADERA_AIF_FORMAT 0x04 +#define MADERA_AIF_RX_BCLK_RATE 0x06 +#define MADERA_AIF_FRAME_CTRL_1 0x07 +#define MADERA_AIF_FRAME_CTRL_2 0x08 +#define MADERA_AIF_FRAME_CTRL_3 0x09 +#define MADERA_AIF_FRAME_CTRL_4 0x0A +#define MADERA_AIF_FRAME_CTRL_5 0x0B +#define MADERA_AIF_FRAME_CTRL_6 0x0C +#define MADERA_AIF_FRAME_CTRL_7 0x0D +#define MADERA_AIF_FRAME_CTRL_8 0x0E +#define MADERA_AIF_FRAME_CTRL_9 0x0F +#define MADERA_AIF_FRAME_CTRL_10 0x10 +#define MADERA_AIF_FRAME_CTRL_11 0x11 +#define MADERA_AIF_FRAME_CTRL_12 0x12 +#define MADERA_AIF_FRAME_CTRL_13 0x13 +#define MADERA_AIF_FRAME_CTRL_14 0x14 +#define MADERA_AIF_FRAME_CTRL_15 0x15 +#define MADERA_AIF_FRAME_CTRL_16 0x16 +#define MADERA_AIF_FRAME_CTRL_17 0x17 +#define MADERA_AIF_FRAME_CTRL_18 0x18 +#define MADERA_AIF_TX_ENABLES 0x19 +#define MADERA_AIF_RX_ENABLES 0x1A +#define MADERA_AIF_FORCE_WRITE 0x1B + +#define MADERA_DSP_CONFIG_1_OFFS 0x00 +#define MADERA_DSP_CONFIG_2_OFFS 0x02 + +#define MADERA_DSP_CLK_SEL_MASK 0x70000 +#define MADERA_DSP_CLK_SEL_SHIFT 16 + +#define MADERA_DSP_RATE_MASK 0x7800 +#define MADERA_DSP_RATE_SHIFT 11 + +#define MADERA_SYSCLK_6MHZ 0 +#define MADERA_SYSCLK_12MHZ 1 +#define MADERA_SYSCLK_24MHZ 2 +#define MADERA_SYSCLK_49MHZ 3 +#define MADERA_SYSCLK_98MHZ 4 + +#define MADERA_DSPCLK_9MHZ 0 +#define MADERA_DSPCLK_18MHZ 1 +#define MADERA_DSPCLK_36MHZ 2 +#define MADERA_DSPCLK_73MHZ 3 +#define MADERA_DSPCLK_147MHZ 4 + +#define MADERA_FLL_VCO_CORNER 141900000 +#define MADERA_FLL_MAX_FREF 13500000 +#define MADERA_FLL_MAX_N 1023 +#define MADERA_FLL_MIN_FOUT 90000000 +#define MADERA_FLL_MAX_FOUT 100000000 +#define MADERA_FLL_MAX_FRATIO 16 +#define MADERA_FLL_MAX_REFDIV 8 +#define MADERA_FLL_OUTDIV 3 +#define MADERA_FLL_VCO_MULT 3 +#define MADERA_FLLAO_MAX_FREF 12288000 +#define MADERA_FLLAO_MIN_N 4 +#define MADERA_FLLAO_MAX_N 1023 +#define MADERA_FLLAO_MAX_FBDIV 254 + +#define MADERA_FLL_SYNCHRONISER_OFFS 0x10 +#define CS47L35_FLL_SYNCHRONISER_OFFS 0xE +#define MADERA_FLL_CONTROL_1_OFFS 0x1 +#define MADERA_FLL_CONTROL_2_OFFS 0x2 +#define MADERA_FLL_CONTROL_3_OFFS 0x3 +#define MADERA_FLL_CONTROL_4_OFFS 0x4 +#define MADERA_FLL_CONTROL_5_OFFS 0x5 +#define MADERA_FLL_CONTROL_6_OFFS 0x6 +#define MADERA_FLL_CONTROL_7_OFFS 0x9 +#define MADERA_FLL_EFS_2_OFFS 0xA +#define MADERA_FLL_SYNCHRONISER_1_OFFS 0x1 +#define MADERA_FLL_SYNCHRONISER_2_OFFS 0x2 +#define MADERA_FLL_SYNCHRONISER_3_OFFS 0x3 +#define MADERA_FLL_SYNCHRONISER_4_OFFS 0x4 +#define MADERA_FLL_SYNCHRONISER_5_OFFS 0x5 +#define MADERA_FLL_SYNCHRONISER_6_OFFS 0x6 +#define MADERA_FLL_SYNCHRONISER_7_OFFS 0x7 +#define MADERA_FLL_SPREAD_SPECTRUM_OFFS 0x9 +#define MADERA_FLL_GPIO_CLOCK_OFFS 0xA + +#define MADERA_FLLAO_CONTROL_1_OFFS 0x1 +#define MADERA_FLLAO_CONTROL_2_OFFS 0x2 +#define MADERA_FLLAO_CONTROL_3_OFFS 0x3 +#define MADERA_FLLAO_CONTROL_4_OFFS 0x4 +#define MADERA_FLLAO_CONTROL_5_OFFS 0x5 +#define MADERA_FLLAO_CONTROL_6_OFFS 0x6 +#define MADERA_FLLAO_CONTROL_7_OFFS 0x8 +#define MADERA_FLLAO_CONTROL_8_OFFS 0xA +#define MADERA_FLLAO_CONTROL_9_OFFS 0xB +#define MADERA_FLLAO_CONTROL_10_OFFS 0xC +#define MADERA_FLLAO_CONTROL_11_OFFS 0xD + +#define MADERA_FMT_DSP_MODE_A 0 +#define MADERA_FMT_DSP_MODE_B 1 +#define MADERA_FMT_I2S_MODE 2 +#define MADERA_FMT_LEFT_JUSTIFIED_MODE 3 + +#define madera_fll_err(_fll, fmt, ...) \ + dev_err(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) +#define madera_fll_warn(_fll, fmt, ...) \ + dev_warn(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) +#define madera_fll_dbg(_fll, fmt, ...) \ + dev_dbg(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) + +#define madera_aif_err(_dai, fmt, ...) \ + dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) +#define madera_aif_warn(_dai, fmt, ...) \ + dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) +#define madera_aif_dbg(_dai, fmt, ...) \ + dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) + +static const int madera_dsp_bus_error_irqs[MADERA_MAX_ADSP] = { + MADERA_IRQ_DSP1_BUS_ERR, + MADERA_IRQ_DSP2_BUS_ERR, + MADERA_IRQ_DSP3_BUS_ERR, + MADERA_IRQ_DSP4_BUS_ERR, + MADERA_IRQ_DSP5_BUS_ERR, + MADERA_IRQ_DSP6_BUS_ERR, + MADERA_IRQ_DSP7_BUS_ERR, +}; + +static void madera_spin_sysclk(struct madera_priv *priv) +{ + struct madera *madera = priv->madera; + unsigned int val; + int ret, i; + + /* Skip this if the chip is down */ + if (pm_runtime_suspended(madera->dev)) + return; + + /* + * Just read a register a few times to ensure the internal + * oscillator sends out a few clocks. + */ + for (i = 0; i < 4; i++) { + ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &val); + if (ret) + dev_err(madera->dev, + "Failed to read sysclk spin %d: %d\n", i, ret); + } + + udelay(300); +} + +int madera_sysclk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + + madera_spin_sysclk(priv); + + return 0; +} +EXPORT_SYMBOL_GPL(madera_sysclk_ev); + +static int madera_check_speaker_overheat(struct madera *madera, + bool *warn, bool *shutdown) +{ + unsigned int val; + int ret; + + ret = regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_15, &val); + if (ret) { + dev_err(madera->dev, "Failed to read thermal status: %d\n", + ret); + return ret; + } + + *warn = val & MADERA_SPK_OVERHEAT_WARN_STS1; + *shutdown = val & MADERA_SPK_OVERHEAT_STS1; + + return 0; +} + +int madera_spk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + bool warn, shutdown; + int ret; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + ret = madera_check_speaker_overheat(madera, &warn, &shutdown); + if (ret) + return ret; + + if (shutdown) { + dev_crit(madera->dev, + "Speaker not enabled due to temperature\n"); + return -EBUSY; + } + + regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, + 1 << w->shift, 1 << w->shift); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, + 1 << w->shift, 0); + break; + default: + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(madera_spk_ev); + +static irqreturn_t madera_thermal_warn(int irq, void *data) +{ + struct madera *madera = data; + bool warn, shutdown; + int ret; + + ret = madera_check_speaker_overheat(madera, &warn, &shutdown); + if (ret || shutdown) { /* for safety attempt to shutdown on error */ + dev_crit(madera->dev, "Thermal shutdown\n"); + ret = regmap_update_bits(madera->regmap, + MADERA_OUTPUT_ENABLES_1, + MADERA_OUT4L_ENA | + MADERA_OUT4R_ENA, 0); + if (ret != 0) + dev_crit(madera->dev, + "Failed to disable speaker outputs: %d\n", + ret); + } else if (warn) { + dev_alert(madera->dev, "Thermal warning\n"); + } else { + dev_info(madera->dev, "Spurious thermal warning\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +int madera_init_overheat(struct madera_priv *priv) +{ + struct madera *madera = priv->madera; + struct device *dev = madera->dev; + int ret; + + ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN, + "Thermal warning", madera_thermal_warn, + madera); + if (ret) + dev_err(dev, "Failed to get thermal warning IRQ: %d\n", ret); + + ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT, + "Thermal shutdown", madera_thermal_warn, + madera); + if (ret) + dev_err(dev, "Failed to get thermal shutdown IRQ: %d\n", ret); + + return 0; +} +EXPORT_SYMBOL_GPL(madera_init_overheat); + +int madera_free_overheat(struct madera_priv *priv) +{ + struct madera *madera = priv->madera; + + madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN, madera); + madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT, madera); + + return 0; +} +EXPORT_SYMBOL_GPL(madera_free_overheat); + +int madera_core_init(struct madera_priv *priv) +{ + int i; + + /* trap undersized array initializers */ + BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]); + BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]); + + mutex_init(&priv->rate_lock); + + for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++) + priv->madera->out_clamp[i] = true; + + return 0; +} +EXPORT_SYMBOL_GPL(madera_core_init); + +int madera_core_free(struct madera_priv *priv) +{ + mutex_destroy(&priv->rate_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(madera_core_free); + +static void madera_debug_dump_domain_groups(const struct madera_priv *priv) +{ + struct madera *madera = priv->madera; + int i; + + for (i = 0; i < ARRAY_SIZE(priv->domain_group_ref); ++i) + dev_dbg(madera->dev, "domain_grp_ref[%d]=%d\n", i, + priv->domain_group_ref[i]); +} + +int madera_domain_clk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + int dom_grp = w->shift; + + if (dom_grp >= ARRAY_SIZE(priv->domain_group_ref)) { + WARN(true, "%s dom_grp exceeds array size\n", __func__); + return -EINVAL; + } + + /* + * We can't rely on the DAPM mutex for locking because we need a lock + * that can safely be called in hw_params + */ + mutex_lock(&priv->rate_lock); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + dev_dbg(priv->madera->dev, "Inc ref on domain group %d\n", + dom_grp); + ++priv->domain_group_ref[dom_grp]; + break; + case SND_SOC_DAPM_POST_PMD: + dev_dbg(priv->madera->dev, "Dec ref on domain group %d\n", + dom_grp); + --priv->domain_group_ref[dom_grp]; + break; + default: + break; + } + + madera_debug_dump_domain_groups(priv); + + mutex_unlock(&priv->rate_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(madera_domain_clk_ev); + +int madera_out1_demux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int ep_sel, mux, change; + bool out_mono; + int ret; + + if (ucontrol->value.enumerated.item[0] > e->items - 1) + return -EINVAL; + + mux = ucontrol->value.enumerated.item[0]; + + snd_soc_dapm_mutex_lock(dapm); + + ep_sel = mux << MADERA_EP_SEL_SHIFT; + + change = snd_soc_component_test_bits(component, MADERA_OUTPUT_ENABLES_1, + MADERA_EP_SEL_MASK, + ep_sel); + if (!change) + goto end; + + /* EP_SEL should not be modified while HP or EP driver is enabled */ + ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, + MADERA_OUT1L_ENA | MADERA_OUT1R_ENA, 0); + if (ret) + dev_warn(madera->dev, "Failed to disable outputs: %d\n", ret); + + usleep_range(2000, 3000); /* wait for wseq to complete */ + + /* change demux setting */ + if (madera->out_clamp[0]) + ret = regmap_update_bits(madera->regmap, + MADERA_OUTPUT_ENABLES_1, + MADERA_EP_SEL_MASK, ep_sel); + if (ret) { + dev_err(madera->dev, "Failed to set OUT1 demux: %d\n", ret); + } else { + /* apply correct setting for mono mode */ + if (!ep_sel && !madera->pdata.codec.out_mono[0]) + out_mono = false; /* stereo HP */ + else + out_mono = true; /* EP or mono HP */ + + ret = madera_set_output_mode(component, 1, out_mono); + if (ret) + dev_warn(madera->dev, + "Failed to set output mode: %d\n", ret); + } + + /* + * if HPDET has disabled the clamp while switching to HPOUT + * OUT1 should remain disabled + */ + if (ep_sel || + (madera->out_clamp[0] && !madera->out_shorted[0])) { + ret = regmap_update_bits(madera->regmap, + MADERA_OUTPUT_ENABLES_1, + MADERA_OUT1L_ENA | MADERA_OUT1R_ENA, + madera->hp_ena); + if (ret) + dev_warn(madera->dev, + "Failed to restore earpiece outputs: %d\n", + ret); + else if (madera->hp_ena) + msleep(34); /* wait for enable wseq */ + else + usleep_range(2000, 3000); /* wait for disable wseq */ + } + +end: + snd_soc_dapm_mutex_unlock(dapm); + + return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); +} +EXPORT_SYMBOL_GPL(madera_out1_demux_put); + +int madera_out1_demux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + unsigned int val; + int ret; + + ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, &val); + if (ret) + return ret; + + val &= MADERA_EP_SEL_MASK; + val >>= MADERA_EP_SEL_SHIFT; + ucontrol->value.enumerated.item[0] = val; + + return 0; +} +EXPORT_SYMBOL_GPL(madera_out1_demux_get); + +static int madera_inmux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + struct regmap *regmap = madera->regmap; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux, val, mask; + unsigned int inmode; + bool changed; + int ret; + + mux = ucontrol->value.enumerated.item[0]; + if (mux > 1) + return -EINVAL; + + val = mux << e->shift_l; + mask = (e->mask << e->shift_l) | MADERA_IN1L_SRC_SE_MASK; + + switch (e->reg) { + case MADERA_ADC_DIGITAL_VOLUME_1L: + inmode = madera->pdata.codec.inmode[0][2 * mux]; + break; + case MADERA_ADC_DIGITAL_VOLUME_1R: + inmode = madera->pdata.codec.inmode[0][1 + (2 * mux)]; + break; + case MADERA_ADC_DIGITAL_VOLUME_2L: + inmode = madera->pdata.codec.inmode[1][2 * mux]; + break; + case MADERA_ADC_DIGITAL_VOLUME_2R: + inmode = madera->pdata.codec.inmode[1][1 + (2 * mux)]; + break; + default: + return -EINVAL; + } + + if (inmode & MADERA_INMODE_SE) + val |= 1 << MADERA_IN1L_SRC_SE_SHIFT; + + dev_dbg(madera->dev, "mux=%u reg=0x%x inmode=0x%x mask=0x%x val=0x%x\n", + mux, e->reg, inmode, mask, val); + + ret = regmap_update_bits_check(regmap, e->reg, mask, val, &changed); + if (ret < 0) + return ret; + + if (changed) + return snd_soc_dapm_mux_update_power(dapm, kcontrol, + mux, e, NULL); + else + return 0; +} + +static const char * const madera_inmux_texts[] = { + "A", + "B", +}; + +static SOC_ENUM_SINGLE_DECL(madera_in1muxl_enum, + MADERA_ADC_DIGITAL_VOLUME_1L, + MADERA_IN1L_SRC_SHIFT, + madera_inmux_texts); + +static SOC_ENUM_SINGLE_DECL(madera_in1muxr_enum, + MADERA_ADC_DIGITAL_VOLUME_1R, + MADERA_IN1R_SRC_SHIFT, + madera_inmux_texts); + +static SOC_ENUM_SINGLE_DECL(madera_in2muxl_enum, + MADERA_ADC_DIGITAL_VOLUME_2L, + MADERA_IN2L_SRC_SHIFT, + madera_inmux_texts); + +static SOC_ENUM_SINGLE_DECL(madera_in2muxr_enum, + MADERA_ADC_DIGITAL_VOLUME_2R, + MADERA_IN2R_SRC_SHIFT, + madera_inmux_texts); + +const struct snd_kcontrol_new madera_inmux[] = { + SOC_DAPM_ENUM_EXT("IN1L Mux", madera_in1muxl_enum, + snd_soc_dapm_get_enum_double, madera_inmux_put), + SOC_DAPM_ENUM_EXT("IN1R Mux", madera_in1muxr_enum, + snd_soc_dapm_get_enum_double, madera_inmux_put), + SOC_DAPM_ENUM_EXT("IN2L Mux", madera_in2muxl_enum, + snd_soc_dapm_get_enum_double, madera_inmux_put), + SOC_DAPM_ENUM_EXT("IN2R Mux", madera_in2muxr_enum, + snd_soc_dapm_get_enum_double, madera_inmux_put), +}; +EXPORT_SYMBOL_GPL(madera_inmux); + +static const char * const madera_dmode_texts[] = { + "Analog", + "Digital", +}; + +static SOC_ENUM_SINGLE_DECL(madera_in1dmode_enum, + MADERA_IN1L_CONTROL, + MADERA_IN1_MODE_SHIFT, + madera_dmode_texts); + +static SOC_ENUM_SINGLE_DECL(madera_in2dmode_enum, + MADERA_IN2L_CONTROL, + MADERA_IN2_MODE_SHIFT, + madera_dmode_texts); + +static SOC_ENUM_SINGLE_DECL(madera_in3dmode_enum, + MADERA_IN3L_CONTROL, + MADERA_IN3_MODE_SHIFT, + madera_dmode_texts); + +const struct snd_kcontrol_new madera_inmode[] = { + SOC_DAPM_ENUM("IN1 Mode", madera_in1dmode_enum), + SOC_DAPM_ENUM("IN2 Mode", madera_in2dmode_enum), + SOC_DAPM_ENUM("IN3 Mode", madera_in3dmode_enum), +}; +EXPORT_SYMBOL_GPL(madera_inmode); + +static bool madera_can_change_grp_rate(const struct madera_priv *priv, + unsigned int reg) +{ + int count; + + switch (reg) { + case MADERA_FX_CTRL1: + count = priv->domain_group_ref[MADERA_DOM_GRP_FX]; + break; + case MADERA_ASRC1_RATE1: + case MADERA_ASRC1_RATE2: + count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC1]; + break; + case MADERA_ASRC2_RATE1: + case MADERA_ASRC2_RATE2: + count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC2]; + break; + case MADERA_ISRC_1_CTRL_1: + case MADERA_ISRC_1_CTRL_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC1]; + break; + case MADERA_ISRC_2_CTRL_1: + case MADERA_ISRC_2_CTRL_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC2]; + break; + case MADERA_ISRC_3_CTRL_1: + case MADERA_ISRC_3_CTRL_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC3]; + break; + case MADERA_ISRC_4_CTRL_1: + case MADERA_ISRC_4_CTRL_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC4]; + break; + case MADERA_OUTPUT_RATE_1: + count = priv->domain_group_ref[MADERA_DOM_GRP_OUT]; + break; + case MADERA_SPD1_TX_CONTROL: + count = priv->domain_group_ref[MADERA_DOM_GRP_SPD]; + break; + case MADERA_DSP1_CONFIG_1: + case MADERA_DSP1_CONFIG_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_DSP1]; + break; + case MADERA_DSP2_CONFIG_1: + case MADERA_DSP2_CONFIG_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_DSP2]; + break; + case MADERA_DSP3_CONFIG_1: + case MADERA_DSP3_CONFIG_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_DSP3]; + break; + case MADERA_DSP4_CONFIG_1: + case MADERA_DSP4_CONFIG_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_DSP4]; + break; + case MADERA_DSP5_CONFIG_1: + case MADERA_DSP5_CONFIG_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_DSP5]; + break; + case MADERA_DSP6_CONFIG_1: + case MADERA_DSP6_CONFIG_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_DSP6]; + break; + case MADERA_DSP7_CONFIG_1: + case MADERA_DSP7_CONFIG_2: + count = priv->domain_group_ref[MADERA_DOM_GRP_DSP7]; + break; + case MADERA_AIF1_RATE_CTRL: + count = priv->domain_group_ref[MADERA_DOM_GRP_AIF1]; + break; + case MADERA_AIF2_RATE_CTRL: + count = priv->domain_group_ref[MADERA_DOM_GRP_AIF2]; + break; + case MADERA_AIF3_RATE_CTRL: + count = priv->domain_group_ref[MADERA_DOM_GRP_AIF3]; + break; + case MADERA_AIF4_RATE_CTRL: + count = priv->domain_group_ref[MADERA_DOM_GRP_AIF4]; + break; + case MADERA_SLIMBUS_RATES_1: + case MADERA_SLIMBUS_RATES_2: + case MADERA_SLIMBUS_RATES_3: + case MADERA_SLIMBUS_RATES_4: + case MADERA_SLIMBUS_RATES_5: + case MADERA_SLIMBUS_RATES_6: + case MADERA_SLIMBUS_RATES_7: + case MADERA_SLIMBUS_RATES_8: + count = priv->domain_group_ref[MADERA_DOM_GRP_SLIMBUS]; + break; + case MADERA_PWM_DRIVE_1: + count = priv->domain_group_ref[MADERA_DOM_GRP_PWM]; + break; + default: + return false; + } + + dev_dbg(priv->madera->dev, "Rate reg 0x%x group ref %d\n", reg, count); + + if (count) + return false; + else + return true; +} + +static int madera_adsp_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int cached_rate; + const int adsp_num = e->shift_l; + int item; + + mutex_lock(&priv->rate_lock); + cached_rate = priv->adsp_rate_cache[adsp_num]; + mutex_unlock(&priv->rate_lock); + + item = snd_soc_enum_val_to_item(e, cached_rate); + ucontrol->value.enumerated.item[0] = item; + + return 0; +} + +static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + const int adsp_num = e->shift_l; + const unsigned int item = ucontrol->value.enumerated.item[0]; + int ret; + + if (item >= e->items) + return -EINVAL; + + /* + * We don't directly write the rate register here but we want to + * maintain consistent behaviour that rate domains cannot be changed + * while in use since this is a hardware requirement + */ + mutex_lock(&priv->rate_lock); + + if (!madera_can_change_grp_rate(priv, priv->adsp[adsp_num].base)) { + dev_warn(priv->madera->dev, + "Cannot change '%s' while in use by active audio paths\n", + kcontrol->id.name); + ret = -EBUSY; + } else { + /* Volatile register so defer until the codec is powered up */ + priv->adsp_rate_cache[adsp_num] = e->values[item]; + ret = 0; + } + + mutex_unlock(&priv->rate_lock); + + return ret; +} + +static const struct soc_enum madera_adsp_rate_enum[] = { + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 0xf, MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 1, 0xf, MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 2, 0xf, MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 3, 0xf, MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 4, 0xf, MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 5, 0xf, MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 6, 0xf, MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), +}; + +const struct snd_kcontrol_new madera_adsp_rate_controls[] = { + SOC_ENUM_EXT("DSP1 Rate", madera_adsp_rate_enum[0], + madera_adsp_rate_get, madera_adsp_rate_put), + SOC_ENUM_EXT("DSP2 Rate", madera_adsp_rate_enum[1], + madera_adsp_rate_get, madera_adsp_rate_put), + SOC_ENUM_EXT("DSP3 Rate", madera_adsp_rate_enum[2], + madera_adsp_rate_get, madera_adsp_rate_put), + SOC_ENUM_EXT("DSP4 Rate", madera_adsp_rate_enum[3], + madera_adsp_rate_get, madera_adsp_rate_put), + SOC_ENUM_EXT("DSP5 Rate", madera_adsp_rate_enum[4], + madera_adsp_rate_get, madera_adsp_rate_put), + SOC_ENUM_EXT("DSP6 Rate", madera_adsp_rate_enum[5], + madera_adsp_rate_get, madera_adsp_rate_put), + SOC_ENUM_EXT("DSP7 Rate", madera_adsp_rate_enum[6], + madera_adsp_rate_get, madera_adsp_rate_put), +}; +EXPORT_SYMBOL_GPL(madera_adsp_rate_controls); + +static int madera_write_adsp_clk_setting(struct madera_priv *priv, + struct wm_adsp *dsp, + unsigned int freq) +{ + unsigned int val; + unsigned int mask = MADERA_DSP_RATE_MASK; + int ret; + + val = priv->adsp_rate_cache[dsp->num - 1] << MADERA_DSP_RATE_SHIFT; + + switch (priv->madera->type) { + case CS47L35: + case CS47L85: + case WM1840: + /* use legacy frequency registers */ + mask |= MADERA_DSP_CLK_SEL_MASK; + val |= (freq << MADERA_DSP_CLK_SEL_SHIFT); + break; + default: + /* Configure exact dsp frequency */ + dev_dbg(priv->madera->dev, "Set DSP frequency to 0x%x\n", freq); + + ret = regmap_write(dsp->regmap, + dsp->base + MADERA_DSP_CONFIG_2_OFFS, freq); + if (ret) + goto err; + break; + } + + ret = regmap_update_bits(dsp->regmap, + dsp->base + MADERA_DSP_CONFIG_1_OFFS, + mask, val); + if (ret) + goto err; + + dev_dbg(priv->madera->dev, "Set DSP clocking to 0x%x\n", val); + + return 0; + +err: + dev_err(dsp->dev, "Failed to set DSP%d clock: %d\n", dsp->num, ret); + + return ret; +} + +int madera_set_adsp_clk(struct madera_priv *priv, int dsp_num, + unsigned int freq) +{ + struct wm_adsp *dsp = &priv->adsp[dsp_num]; + struct madera *madera = priv->madera; + unsigned int cur, new; + int ret; + + /* + * This is called at a higher DAPM priority than the mux widgets so + * the muxes are still off at this point and it's safe to change + * the rate domain control. + * Also called at a lower DAPM priority than the domain group widgets + * so locking the reads of adsp_rate_cache is not necessary as we know + * changes are locked out by the domain_group_ref reference count. + */ + + ret = regmap_read(dsp->regmap, dsp->base, &cur); + if (ret) { + dev_err(madera->dev, + "Failed to read current DSP rate: %d\n", ret); + return ret; + } + + cur &= MADERA_DSP_RATE_MASK; + + new = priv->adsp_rate_cache[dsp->num - 1] << MADERA_DSP_RATE_SHIFT; + + if (new == cur) { + dev_dbg(madera->dev, "DSP rate not changed\n"); + return madera_write_adsp_clk_setting(priv, dsp, freq); + } else { + dev_dbg(madera->dev, "DSP rate changed\n"); + + /* The write must be guarded by a number of SYSCLK cycles */ + madera_spin_sysclk(priv); + ret = madera_write_adsp_clk_setting(priv, dsp, freq); + madera_spin_sysclk(priv); + return ret; + } +} +EXPORT_SYMBOL_GPL(madera_set_adsp_clk); + +int madera_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int item = ucontrol->value.enumerated.item[0]; + unsigned int val; + int ret; + + if (item >= e->items) + return -EINVAL; + + /* + * Prevent the domain powering up while we're checking whether it's + * safe to change rate domain + */ + mutex_lock(&priv->rate_lock); + + ret = snd_soc_component_read(component, e->reg, &val); + if (ret < 0) { + dev_warn(priv->madera->dev, "Failed to read 0x%x (%d)\n", + e->reg, ret); + goto out; + } + val >>= e->shift_l; + val &= e->mask; + if (snd_soc_enum_item_to_val(e, item) == val) { + ret = 0; + goto out; + } + + if (!madera_can_change_grp_rate(priv, e->reg)) { + dev_warn(priv->madera->dev, + "Cannot change '%s' while in use by active audio paths\n", + kcontrol->id.name); + ret = -EBUSY; + } else { + /* The write must be guarded by a number of SYSCLK cycles */ + madera_spin_sysclk(priv); + ret = snd_soc_put_enum_double(kcontrol, ucontrol); + madera_spin_sysclk(priv); + } +out: + mutex_unlock(&priv->rate_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(madera_rate_put); + +static void madera_configure_input_mode(struct madera *madera) +{ + unsigned int dig_mode, ana_mode_l, ana_mode_r; + int max_analogue_inputs, max_dmic_sup, i; + + switch (madera->type) { + case CS47L35: + max_analogue_inputs = 2; + max_dmic_sup = 2; + break; + case CS47L85: + case WM1840: + max_analogue_inputs = 3; + max_dmic_sup = 3; + break; + case CS47L90: + case CS47L91: + max_analogue_inputs = 2; + max_dmic_sup = 2; + break; + default: + max_analogue_inputs = 2; + max_dmic_sup = 4; + break; + } + + /* + * Initialize input modes from the A settings. For muxed inputs the + * B settings will be applied if the mux is changed + */ + for (i = 0; i < max_dmic_sup; i++) { + dev_dbg(madera->dev, "IN%d mode %u:%u:%u:%u\n", i + 1, + madera->pdata.codec.inmode[i][0], + madera->pdata.codec.inmode[i][1], + madera->pdata.codec.inmode[i][2], + madera->pdata.codec.inmode[i][3]); + + dig_mode = madera->pdata.codec.dmic_ref[i] << + MADERA_IN1_DMIC_SUP_SHIFT; + + switch (madera->pdata.codec.inmode[i][0]) { + case MADERA_INMODE_DIFF: + ana_mode_l = 0; + break; + case MADERA_INMODE_SE: + ana_mode_l = 1 << MADERA_IN1L_SRC_SE_SHIFT; + break; + default: + dev_warn(madera->dev, + "IN%dAL Illegal inmode %u ignored\n", + i + 1, madera->pdata.codec.inmode[i][0]); + continue; + } + + switch (madera->pdata.codec.inmode[i][1]) { + case MADERA_INMODE_DIFF: + ana_mode_r = 0; + break; + case MADERA_INMODE_SE: + ana_mode_r = 1 << MADERA_IN1R_SRC_SE_SHIFT; + break; + default: + dev_warn(madera->dev, + "IN%dAR Illegal inmode %u ignored\n", + i + 1, madera->pdata.codec.inmode[i][1]); + continue; + } + + dev_dbg(madera->dev, + "IN%dA DMIC mode=0x%x Analogue mode=0x%x,0x%x\n", + i + 1, dig_mode, ana_mode_l, ana_mode_r); + + regmap_update_bits(madera->regmap, + MADERA_IN1L_CONTROL + (i * 8), + MADERA_IN1_DMIC_SUP_MASK, dig_mode); + + if (i >= max_analogue_inputs) + continue; + + regmap_update_bits(madera->regmap, + MADERA_ADC_DIGITAL_VOLUME_1L + (i * 8), + MADERA_IN1L_SRC_SE_MASK, ana_mode_l); + + regmap_update_bits(madera->regmap, + MADERA_ADC_DIGITAL_VOLUME_1R + (i * 8), + MADERA_IN1R_SRC_SE_MASK, ana_mode_r); + } +} + +int madera_init_inputs(struct snd_soc_component *component) +{ + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + + madera_configure_input_mode(madera); + + return 0; +} +EXPORT_SYMBOL_GPL(madera_init_inputs); + +static const struct snd_soc_dapm_route madera_mono_routes[] = { + { "OUT1R", NULL, "OUT1L" }, + { "OUT2R", NULL, "OUT2L" }, + { "OUT3R", NULL, "OUT3L" }, + { "OUT4R", NULL, "OUT4L" }, + { "OUT5R", NULL, "OUT5L" }, + { "OUT6R", NULL, "OUT6L" }, +}; + +int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + const struct madera_codec_pdata *pdata = &madera->pdata.codec; + unsigned int val; + int i; + + if (n_mono_routes > MADERA_MAX_OUTPUT) { + dev_warn(madera->dev, + "Requested %d mono outputs, using maximum allowed %d\n", + n_mono_routes, MADERA_MAX_OUTPUT); + n_mono_routes = MADERA_MAX_OUTPUT; + } + + for (i = 0; i < n_mono_routes; i++) { + /* Default is 0 so noop with defaults */ + if (pdata->out_mono[i]) { + val = MADERA_OUT1_MONO; + snd_soc_dapm_add_routes(dapm, + &madera_mono_routes[i], 1); + } else { + val = 0; + } + + regmap_update_bits(madera->regmap, + MADERA_OUTPUT_PATH_CONFIG_1L + (i * 8), + MADERA_OUT1_MONO, val); + + dev_dbg(madera->dev, "OUT%d mono=0x%x\n", i + 1, val); + } + + for (i = 0; i < MADERA_MAX_PDM_SPK; i++) { + dev_dbg(madera->dev, "PDM%d fmt=0x%x mute=0x%x\n", i + 1, + pdata->pdm_fmt[i], pdata->pdm_mute[i]); + + if (pdata->pdm_mute[i]) + regmap_update_bits(madera->regmap, + MADERA_PDM_SPK1_CTRL_1 + (i * 2), + MADERA_SPK1_MUTE_ENDIAN_MASK | + MADERA_SPK1_MUTE_SEQ1_MASK, + pdata->pdm_mute[i]); + + if (pdata->pdm_fmt[i]) + regmap_update_bits(madera->regmap, + MADERA_PDM_SPK1_CTRL_2 + (i * 2), + MADERA_SPK1_FMT_MASK, + pdata->pdm_fmt[i]); + } + + return 0; +} +EXPORT_SYMBOL_GPL(madera_init_outputs); + +int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num, + irq_handler_t handler) +{ + struct madera *madera = priv->madera; + int ret; + + ret = madera_request_irq(madera, + madera_dsp_bus_error_irqs[dsp_num], + "ADSP2 bus error", + handler, + &priv->adsp[dsp_num]); + if (ret) + dev_err(madera->dev, + "Failed to request DSP Lock region IRQ: %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(madera_init_bus_error_irq); + +void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num) +{ + struct madera *madera = priv->madera; + + madera_free_irq(madera, + madera_dsp_bus_error_irqs[dsp_num], + &priv->adsp[dsp_num]); +} +EXPORT_SYMBOL_GPL(madera_free_bus_error_irq); + +const char * const madera_mixer_texts[] = { + "None", + "Tone Generator 1", + "Tone Generator 2", + "Haptics", + "AEC1", + "AEC2", + "Mic Mute Mixer", + "Noise Generator", + "IN1L", + "IN1R", + "IN2L", + "IN2R", + "IN3L", + "IN3R", + "IN4L", + "IN4R", + "IN5L", + "IN5R", + "IN6L", + "IN6R", + "AIF1RX1", + "AIF1RX2", + "AIF1RX3", + "AIF1RX4", + "AIF1RX5", + "AIF1RX6", + "AIF1RX7", + "AIF1RX8", + "AIF2RX1", + "AIF2RX2", + "AIF2RX3", + "AIF2RX4", + "AIF2RX5", + "AIF2RX6", + "AIF2RX7", + "AIF2RX8", + "AIF3RX1", + "AIF3RX2", + "AIF3RX3", + "AIF3RX4", + "AIF4RX1", + "AIF4RX2", + "SLIMRX1", + "SLIMRX2", + "SLIMRX3", + "SLIMRX4", + "SLIMRX5", + "SLIMRX6", + "SLIMRX7", + "SLIMRX8", + "EQ1", + "EQ2", + "EQ3", + "EQ4", + "DRC1L", + "DRC1R", + "DRC2L", + "DRC2R", + "LHPF1", + "LHPF2", + "LHPF3", + "LHPF4", + "DSP1.1", + "DSP1.2", + "DSP1.3", + "DSP1.4", + "DSP1.5", + "DSP1.6", + "DSP2.1", + "DSP2.2", + "DSP2.3", + "DSP2.4", + "DSP2.5", + "DSP2.6", + "DSP3.1", + "DSP3.2", + "DSP3.3", + "DSP3.4", + "DSP3.5", + "DSP3.6", + "DSP4.1", + "DSP4.2", + "DSP4.3", + "DSP4.4", + "DSP4.5", + "DSP4.6", + "DSP5.1", + "DSP5.2", + "DSP5.3", + "DSP5.4", + "DSP5.5", + "DSP5.6", + "DSP6.1", + "DSP6.2", + "DSP6.3", + "DSP6.4", + "DSP6.5", + "DSP6.6", + "DSP7.1", + "DSP7.2", + "DSP7.3", + "DSP7.4", + "DSP7.5", + "DSP7.6", + "ASRC1IN1L", + "ASRC1IN1R", + "ASRC1IN2L", + "ASRC1IN2R", + "ASRC2IN1L", + "ASRC2IN1R", + "ASRC2IN2L", + "ASRC2IN2R", + "ISRC1INT1", + "ISRC1INT2", + "ISRC1INT3", + "ISRC1INT4", + "ISRC1DEC1", + "ISRC1DEC2", + "ISRC1DEC3", + "ISRC1DEC4", + "ISRC2INT1", + "ISRC2INT2", + "ISRC2INT3", + "ISRC2INT4", + "ISRC2DEC1", + "ISRC2DEC2", + "ISRC2DEC3", + "ISRC2DEC4", + "ISRC3INT1", + "ISRC3INT2", + "ISRC3INT3", + "ISRC3INT4", + "ISRC3DEC1", + "ISRC3DEC2", + "ISRC3DEC3", + "ISRC3DEC4", + "ISRC4INT1", + "ISRC4INT2", + "ISRC4DEC1", + "ISRC4DEC2", + "DFC1", + "DFC2", + "DFC3", + "DFC4", + "DFC5", + "DFC6", + "DFC7", + "DFC8", +}; +EXPORT_SYMBOL_GPL(madera_mixer_texts); + +const unsigned int madera_mixer_values[] = { + 0x00, /* None */ + 0x04, /* Tone Generator 1 */ + 0x05, /* Tone Generator 2 */ + 0x06, /* Haptics */ + 0x08, /* AEC */ + 0x09, /* AEC2 */ + 0x0c, /* Noise mixer */ + 0x0d, /* Comfort noise */ + 0x10, /* IN1L */ + 0x11, + 0x12, + 0x13, + 0x14, + 0x15, + 0x16, + 0x17, + 0x18, + 0x19, + 0x1A, + 0x1B, + 0x20, /* AIF1RX1 */ + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, + 0x26, + 0x27, + 0x28, /* AIF2RX1 */ + 0x29, + 0x2a, + 0x2b, + 0x2c, + 0x2d, + 0x2e, + 0x2f, + 0x30, /* AIF3RX1 */ + 0x31, + 0x32, + 0x33, + 0x34, /* AIF4RX1 */ + 0x35, + 0x38, /* SLIMRX1 */ + 0x39, + 0x3a, + 0x3b, + 0x3c, + 0x3d, + 0x3e, + 0x3f, + 0x50, /* EQ1 */ + 0x51, + 0x52, + 0x53, + 0x58, /* DRC1L */ + 0x59, + 0x5a, + 0x5b, + 0x60, /* LHPF1 */ + 0x61, + 0x62, + 0x63, + 0x68, /* DSP1.1 */ + 0x69, + 0x6a, + 0x6b, + 0x6c, + 0x6d, + 0x70, /* DSP2.1 */ + 0x71, + 0x72, + 0x73, + 0x74, + 0x75, + 0x78, /* DSP3.1 */ + 0x79, + 0x7a, + 0x7b, + 0x7c, + 0x7d, + 0x80, /* DSP4.1 */ + 0x81, + 0x82, + 0x83, + 0x84, + 0x85, + 0x88, /* DSP5.1 */ + 0x89, + 0x8a, + 0x8b, + 0x8c, + 0x8d, + 0xc0, /* DSP6.1 */ + 0xc1, + 0xc2, + 0xc3, + 0xc4, + 0xc5, + 0xc8, /* DSP7.1 */ + 0xc9, + 0xca, + 0xcb, + 0xcc, + 0xcd, + 0x90, /* ASRC1IN1L */ + 0x91, + 0x92, + 0x93, + 0x94, /* ASRC2IN1L */ + 0x95, + 0x96, + 0x97, + 0xa0, /* ISRC1INT1 */ + 0xa1, + 0xa2, + 0xa3, + 0xa4, /* ISRC1DEC1 */ + 0xa5, + 0xa6, + 0xa7, + 0xa8, /* ISRC2DEC1 */ + 0xa9, + 0xaa, + 0xab, + 0xac, /* ISRC2INT1 */ + 0xad, + 0xae, + 0xaf, + 0xb0, /* ISRC3DEC1 */ + 0xb1, + 0xb2, + 0xb3, + 0xb4, /* ISRC3INT1 */ + 0xb5, + 0xb6, + 0xb7, + 0xb8, /* ISRC4INT1 */ + 0xb9, + 0xbc, /* ISRC4DEC1 */ + 0xbd, + 0xf8, /* DFC1 */ + 0xf9, + 0xfa, + 0xfb, + 0xfc, + 0xfd, + 0xfe, + 0xff, /* DFC8 */ +}; +EXPORT_SYMBOL_GPL(madera_mixer_values); + +const DECLARE_TLV_DB_SCALE(madera_ana_tlv, 0, 100, 0); +EXPORT_SYMBOL_GPL(madera_ana_tlv); + +const DECLARE_TLV_DB_SCALE(madera_eq_tlv, -1200, 100, 0); +EXPORT_SYMBOL_GPL(madera_eq_tlv); + +const DECLARE_TLV_DB_SCALE(madera_digital_tlv, -6400, 50, 0); +EXPORT_SYMBOL_GPL(madera_digital_tlv); + +const DECLARE_TLV_DB_SCALE(madera_noise_tlv, -13200, 600, 0); +EXPORT_SYMBOL_GPL(madera_noise_tlv); + +const DECLARE_TLV_DB_SCALE(madera_ng_tlv, -12000, 600, 0); +EXPORT_SYMBOL_GPL(madera_ng_tlv); + +const DECLARE_TLV_DB_SCALE(madera_mixer_tlv, -3200, 100, 0); +EXPORT_SYMBOL_GPL(madera_mixer_tlv); + +const char * const madera_rate_text[MADERA_RATE_ENUM_SIZE] = { + "SYNCCLK rate 1", "SYNCCLK rate 2", "SYNCCLK rate 3", + "ASYNCCLK rate 1", "ASYNCCLK rate 2", +}; +EXPORT_SYMBOL_GPL(madera_rate_text); + +const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE] = { + 0x0, 0x1, 0x2, 0x8, 0x9, +}; +EXPORT_SYMBOL_GPL(madera_rate_val); + +static const char * const madera_dfc_width_text[MADERA_DFC_WIDTH_ENUM_SIZE] = { + "8 bit", "16 bit", "20 bit", "24 bit", "32 bit", +}; + +static const unsigned int madera_dfc_width_val[MADERA_DFC_WIDTH_ENUM_SIZE] = { + 7, 15, 19, 23, 31, +}; + +static const char * const madera_dfc_type_text[MADERA_DFC_TYPE_ENUM_SIZE] = { + "Fixed", "Unsigned Fixed", "Single Precision Floating", + "Half Precision Floating", "Arm Alternative Floating", +}; + +static const unsigned int madera_dfc_type_val[MADERA_DFC_TYPE_ENUM_SIZE] = { + 0, 1, 2, 4, 5, +}; + +const struct soc_enum madera_dfc_width[] = { + SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_RX, + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + MADERA_DFC1_RX_DATA_WIDTH_MASK >> + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_TX, + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + MADERA_DFC1_TX_DATA_WIDTH_MASK >> + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_RX, + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + MADERA_DFC1_RX_DATA_WIDTH_MASK >> + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_TX, + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + MADERA_DFC1_TX_DATA_WIDTH_MASK >> + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_RX, + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + MADERA_DFC1_RX_DATA_WIDTH_MASK >> + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_TX, + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + MADERA_DFC1_TX_DATA_WIDTH_MASK >> + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_RX, + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + MADERA_DFC1_RX_DATA_WIDTH_MASK >> + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_TX, + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + MADERA_DFC1_TX_DATA_WIDTH_MASK >> + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_RX, + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + MADERA_DFC1_RX_DATA_WIDTH_MASK >> + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_TX, + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + MADERA_DFC1_TX_DATA_WIDTH_MASK >> + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_RX, + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + MADERA_DFC1_RX_DATA_WIDTH_MASK >> + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_TX, + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + MADERA_DFC1_TX_DATA_WIDTH_MASK >> + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_RX, + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + MADERA_DFC1_RX_DATA_WIDTH_MASK >> + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_TX, + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + MADERA_DFC1_TX_DATA_WIDTH_MASK >> + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_RX, + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + MADERA_DFC1_RX_DATA_WIDTH_MASK >> + MADERA_DFC1_RX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_TX, + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + MADERA_DFC1_TX_DATA_WIDTH_MASK >> + MADERA_DFC1_TX_DATA_WIDTH_SHIFT, + ARRAY_SIZE(madera_dfc_width_text), + madera_dfc_width_text, + madera_dfc_width_val), +}; +EXPORT_SYMBOL_GPL(madera_dfc_width); + +const struct soc_enum madera_dfc_type[] = { + SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_RX, + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + MADERA_DFC1_RX_DATA_TYPE_MASK >> + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_TX, + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + MADERA_DFC1_TX_DATA_TYPE_MASK >> + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_RX, + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + MADERA_DFC1_RX_DATA_TYPE_MASK >> + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_TX, + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + MADERA_DFC1_TX_DATA_TYPE_MASK >> + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_RX, + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + MADERA_DFC1_RX_DATA_TYPE_MASK >> + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_TX, + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + MADERA_DFC1_TX_DATA_TYPE_MASK >> + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_RX, + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + MADERA_DFC1_RX_DATA_TYPE_MASK >> + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_TX, + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + MADERA_DFC1_TX_DATA_TYPE_MASK >> + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_RX, + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + MADERA_DFC1_RX_DATA_TYPE_MASK >> + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_TX, + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + MADERA_DFC1_TX_DATA_TYPE_MASK >> + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_RX, + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + MADERA_DFC1_RX_DATA_TYPE_MASK >> + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_TX, + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + MADERA_DFC1_TX_DATA_TYPE_MASK >> + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_RX, + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + MADERA_DFC1_RX_DATA_TYPE_MASK >> + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_TX, + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + MADERA_DFC1_TX_DATA_TYPE_MASK >> + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_RX, + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + MADERA_DFC1_RX_DATA_TYPE_MASK >> + MADERA_DFC1_RX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_TX, + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + MADERA_DFC1_TX_DATA_TYPE_MASK >> + MADERA_DFC1_TX_DATA_TYPE_SHIFT, + ARRAY_SIZE(madera_dfc_type_text), + madera_dfc_type_text, + madera_dfc_type_val), +}; +EXPORT_SYMBOL_GPL(madera_dfc_type); + +const struct soc_enum madera_isrc_fsh[] = { + SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_1_CTRL_1, + MADERA_ISRC1_FSH_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_2_CTRL_1, + MADERA_ISRC2_FSH_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_3_CTRL_1, + MADERA_ISRC3_FSH_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_4_CTRL_1, + MADERA_ISRC4_FSH_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + +}; +EXPORT_SYMBOL_GPL(madera_isrc_fsh); + +const struct soc_enum madera_isrc_fsl[] = { + SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_1_CTRL_2, + MADERA_ISRC1_FSL_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_2_CTRL_2, + MADERA_ISRC2_FSL_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_3_CTRL_2, + MADERA_ISRC3_FSL_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_4_CTRL_2, + MADERA_ISRC4_FSL_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + +}; +EXPORT_SYMBOL_GPL(madera_isrc_fsl); + +const struct soc_enum madera_asrc1_rate[] = { + SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1, + MADERA_ASRC1_RATE1_SHIFT, 0xf, + MADERA_SYNC_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2, + MADERA_ASRC1_RATE1_SHIFT, 0xf, + 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); + +const struct soc_enum madera_asrc2_rate[] = { + SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1, + MADERA_ASRC2_RATE1_SHIFT, 0xf, + MADERA_SYNC_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE2, + MADERA_ASRC2_RATE2_SHIFT, 0xf, + 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); + +static const char * const madera_vol_ramp_text[] = { + "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", + "15ms/6dB", "30ms/6dB", +}; + +SOC_ENUM_SINGLE_DECL(madera_in_vd_ramp, + MADERA_INPUT_VOLUME_RAMP, + MADERA_IN_VD_RAMP_SHIFT, + madera_vol_ramp_text); +EXPORT_SYMBOL_GPL(madera_in_vd_ramp); + +SOC_ENUM_SINGLE_DECL(madera_in_vi_ramp, + MADERA_INPUT_VOLUME_RAMP, + MADERA_IN_VI_RAMP_SHIFT, + madera_vol_ramp_text); +EXPORT_SYMBOL_GPL(madera_in_vi_ramp); + +SOC_ENUM_SINGLE_DECL(madera_out_vd_ramp, + MADERA_OUTPUT_VOLUME_RAMP, + MADERA_OUT_VD_RAMP_SHIFT, + madera_vol_ramp_text); +EXPORT_SYMBOL_GPL(madera_out_vd_ramp); + +SOC_ENUM_SINGLE_DECL(madera_out_vi_ramp, + MADERA_OUTPUT_VOLUME_RAMP, + MADERA_OUT_VI_RAMP_SHIFT, + madera_vol_ramp_text); +EXPORT_SYMBOL_GPL(madera_out_vi_ramp); + +static const char * const madera_lhpf_mode_text[] = { + "Low-pass", "High-pass" +}; + +SOC_ENUM_SINGLE_DECL(madera_lhpf1_mode, + MADERA_HPLPF1_1, + MADERA_LHPF1_MODE_SHIFT, + madera_lhpf_mode_text); +EXPORT_SYMBOL_GPL(madera_lhpf1_mode); + +SOC_ENUM_SINGLE_DECL(madera_lhpf2_mode, + MADERA_HPLPF2_1, + MADERA_LHPF2_MODE_SHIFT, + madera_lhpf_mode_text); +EXPORT_SYMBOL_GPL(madera_lhpf2_mode); + +SOC_ENUM_SINGLE_DECL(madera_lhpf3_mode, + MADERA_HPLPF3_1, + MADERA_LHPF3_MODE_SHIFT, + madera_lhpf_mode_text); +EXPORT_SYMBOL_GPL(madera_lhpf3_mode); + +SOC_ENUM_SINGLE_DECL(madera_lhpf4_mode, + MADERA_HPLPF4_1, + MADERA_LHPF4_MODE_SHIFT, + madera_lhpf_mode_text); +EXPORT_SYMBOL_GPL(madera_lhpf4_mode); + +static const char * const madera_ng_hold_text[] = { + "30ms", "120ms", "250ms", "500ms", +}; + +SOC_ENUM_SINGLE_DECL(madera_ng_hold, + MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_HOLD_SHIFT, + madera_ng_hold_text); +EXPORT_SYMBOL_GPL(madera_ng_hold); + +static const char * const madera_in_hpf_cut_text[] = { + "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" +}; + +SOC_ENUM_SINGLE_DECL(madera_in_hpf_cut_enum, + MADERA_HPF_CONTROL, + MADERA_IN_HPF_CUT_SHIFT, + madera_in_hpf_cut_text); +EXPORT_SYMBOL_GPL(madera_in_hpf_cut_enum); + +static const char * const madera_in_dmic_osr_text[MADERA_OSR_ENUM_SIZE] = { + "384kHz", "768kHz", "1.536MHz", "3.072MHz", "6.144MHz", +}; + +static const unsigned int madera_in_dmic_osr_val[MADERA_OSR_ENUM_SIZE] = { + 2, 3, 4, 5, 6, +}; + +const struct soc_enum madera_in_dmic_osr[] = { + SOC_VALUE_ENUM_SINGLE(MADERA_DMIC1L_CONTROL, MADERA_IN1_OSR_SHIFT, + 0x7, MADERA_OSR_ENUM_SIZE, + madera_in_dmic_osr_text, madera_in_dmic_osr_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DMIC2L_CONTROL, MADERA_IN2_OSR_SHIFT, + 0x7, MADERA_OSR_ENUM_SIZE, + madera_in_dmic_osr_text, madera_in_dmic_osr_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DMIC3L_CONTROL, MADERA_IN3_OSR_SHIFT, + 0x7, MADERA_OSR_ENUM_SIZE, + madera_in_dmic_osr_text, madera_in_dmic_osr_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DMIC4L_CONTROL, MADERA_IN4_OSR_SHIFT, + 0x7, MADERA_OSR_ENUM_SIZE, + madera_in_dmic_osr_text, madera_in_dmic_osr_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DMIC5L_CONTROL, MADERA_IN5_OSR_SHIFT, + 0x7, MADERA_OSR_ENUM_SIZE, + madera_in_dmic_osr_text, madera_in_dmic_osr_val), + SOC_VALUE_ENUM_SINGLE(MADERA_DMIC6L_CONTROL, MADERA_IN6_OSR_SHIFT, + 0x7, MADERA_OSR_ENUM_SIZE, + madera_in_dmic_osr_text, madera_in_dmic_osr_val), +}; +EXPORT_SYMBOL_GPL(madera_in_dmic_osr); + +static const char * const madera_anc_input_src_text[] = { + "None", "IN1", "IN2", "IN3", "IN4", "IN5", "IN6", +}; + +static const char * const madera_anc_channel_src_text[] = { + "None", "Left", "Right", "Combine", +}; + +const struct soc_enum madera_anc_input_src[] = { + SOC_ENUM_SINGLE(MADERA_ANC_SRC, + MADERA_IN_RXANCL_SEL_SHIFT, + ARRAY_SIZE(madera_anc_input_src_text), + madera_anc_input_src_text), + SOC_ENUM_SINGLE(MADERA_FCL_ADC_REFORMATTER_CONTROL, + MADERA_FCL_MIC_MODE_SEL_SHIFT, + ARRAY_SIZE(madera_anc_channel_src_text), + madera_anc_channel_src_text), + SOC_ENUM_SINGLE(MADERA_ANC_SRC, + MADERA_IN_RXANCR_SEL_SHIFT, + ARRAY_SIZE(madera_anc_input_src_text), + madera_anc_input_src_text), + SOC_ENUM_SINGLE(MADERA_FCR_ADC_REFORMATTER_CONTROL, + MADERA_FCR_MIC_MODE_SEL_SHIFT, + ARRAY_SIZE(madera_anc_channel_src_text), + madera_anc_channel_src_text), +}; +EXPORT_SYMBOL_GPL(madera_anc_input_src); + +static const char * const madera_anc_ng_texts[] = { + "None", "Internal", "External", +}; + +SOC_ENUM_SINGLE_DECL(madera_anc_ng_enum, SND_SOC_NOPM, 0, madera_anc_ng_texts); +EXPORT_SYMBOL_GPL(madera_anc_ng_enum); + +static const char * const madera_out_anc_src_text[] = { + "None", "RXANCL", "RXANCR", +}; + +const struct soc_enum madera_output_anc_src[] = { + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_1L, + MADERA_OUT1L_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_1R, + MADERA_OUT1R_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_2L, + MADERA_OUT2L_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_2R, + MADERA_OUT2R_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_3L, + MADERA_OUT3L_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_3R, + MADERA_OUT3R_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_4L, + MADERA_OUT4L_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_4R, + MADERA_OUT4R_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_5L, + MADERA_OUT5L_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_5R, + MADERA_OUT5R_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_6L, + MADERA_OUT6L_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), + SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_6R, + MADERA_OUT6R_ANC_SRC_SHIFT, + ARRAY_SIZE(madera_out_anc_src_text), + madera_out_anc_src_text), +}; +EXPORT_SYMBOL_GPL(madera_output_anc_src); + +int madera_dfc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int reg = e->reg; + unsigned int val; + int ret = 0; + + reg = ((reg / 6) * 6) - 2; + + snd_soc_dapm_mutex_lock(dapm); + + ret = snd_soc_component_read(component, reg, &val); + if (ret) + goto exit; + + if (val & MADERA_DFC1_ENA) { + ret = -EBUSY; + dev_err(component->dev, "Can't change mode on an active DFC\n"); + goto exit; + } + + ret = snd_soc_put_enum_double(kcontrol, ucontrol); +exit: + snd_soc_dapm_mutex_unlock(dapm); + + return ret; +} +EXPORT_SYMBOL_GPL(madera_dfc_put); + +int madera_lp_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + unsigned int val, mask; + int ret; + + snd_soc_dapm_mutex_lock(dapm); + + /* Cannot change lp mode on an active input */ + ret = snd_soc_component_read(component, MADERA_INPUT_ENABLES, &val); + if (ret) + goto exit; + mask = (mc->reg - MADERA_ADC_DIGITAL_VOLUME_1L) / 4; + mask ^= 0x1; /* Flip bottom bit for channel order */ + + if (val & (1 << mask)) { + ret = -EBUSY; + dev_err(component->dev, + "Can't change lp mode on an active input\n"); + goto exit; + } + + ret = snd_soc_put_volsw(kcontrol, ucontrol); + +exit: + snd_soc_dapm_mutex_unlock(dapm); + + return ret; +} +EXPORT_SYMBOL_GPL(madera_lp_mode_put); + +const struct snd_kcontrol_new madera_dsp_trigger_output_mux[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), +}; +EXPORT_SYMBOL_GPL(madera_dsp_trigger_output_mux); + +const struct snd_kcontrol_new madera_drc_activity_output_mux[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), +}; +EXPORT_SYMBOL_GPL(madera_drc_activity_output_mux); + +static void madera_in_set_vu(struct madera_priv *priv, bool enable) +{ + unsigned int val; + int i, ret; + + if (enable) + val = MADERA_IN_VU; + else + val = 0; + + for (i = 0; i < priv->num_inputs; i++) { + ret = regmap_update_bits(priv->madera->regmap, + MADERA_ADC_DIGITAL_VOLUME_1L + (i * 4), + MADERA_IN_VU, val); + if (ret) + dev_warn(priv->madera->dev, + "Failed to modify VU bits: %d\n", ret); + } +} + +int madera_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + unsigned int reg, val; + int ret; + + if (w->shift % 2) + reg = MADERA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8); + else + reg = MADERA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + priv->in_pending++; + break; + case SND_SOC_DAPM_POST_PMU: + priv->in_pending--; + snd_soc_component_update_bits(component, reg, + MADERA_IN1L_MUTE, 0); + + /* If this is the last input pending then allow VU */ + if (priv->in_pending == 0) { + usleep_range(1000, 3000); + madera_in_set_vu(priv, true); + } + break; + case SND_SOC_DAPM_PRE_PMD: + snd_soc_component_update_bits(component, reg, + MADERA_IN1L_MUTE | MADERA_IN_VU, + MADERA_IN1L_MUTE | MADERA_IN_VU); + break; + case SND_SOC_DAPM_POST_PMD: + /* Disable volume updates if no inputs are enabled */ + ret = snd_soc_component_read(component, MADERA_INPUT_ENABLES, + &val); + if (!ret && !val) + madera_in_set_vu(priv, false); + break; + default: + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(madera_in_ev); + +int madera_out_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + int out_up_delay; + + switch (madera->type) { + case CS47L90: + case CS47L91: + out_up_delay = 6; + break; + default: + out_up_delay = 17; + break; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + switch (w->shift) { + case MADERA_OUT1L_ENA_SHIFT: + case MADERA_OUT1R_ENA_SHIFT: + case MADERA_OUT2L_ENA_SHIFT: + case MADERA_OUT2R_ENA_SHIFT: + case MADERA_OUT3L_ENA_SHIFT: + case MADERA_OUT3R_ENA_SHIFT: + priv->out_up_pending++; + priv->out_up_delay += out_up_delay; + break; + default: + break; + } + break; + + case SND_SOC_DAPM_POST_PMU: + switch (w->shift) { + case MADERA_OUT1L_ENA_SHIFT: + case MADERA_OUT1R_ENA_SHIFT: + case MADERA_OUT2L_ENA_SHIFT: + case MADERA_OUT2R_ENA_SHIFT: + case MADERA_OUT3L_ENA_SHIFT: + case MADERA_OUT3R_ENA_SHIFT: + priv->out_up_pending--; + if (!priv->out_up_pending) { + msleep(priv->out_up_delay); + priv->out_up_delay = 0; + } + break; + + default: + break; + } + break; + + case SND_SOC_DAPM_PRE_PMD: + switch (w->shift) { + case MADERA_OUT1L_ENA_SHIFT: + case MADERA_OUT1R_ENA_SHIFT: + case MADERA_OUT2L_ENA_SHIFT: + case MADERA_OUT2R_ENA_SHIFT: + case MADERA_OUT3L_ENA_SHIFT: + case MADERA_OUT3R_ENA_SHIFT: + priv->out_down_pending++; + priv->out_down_delay++; + break; + default: + break; + } + break; + + case SND_SOC_DAPM_POST_PMD: + switch (w->shift) { + case MADERA_OUT1L_ENA_SHIFT: + case MADERA_OUT1R_ENA_SHIFT: + case MADERA_OUT2L_ENA_SHIFT: + case MADERA_OUT2R_ENA_SHIFT: + case MADERA_OUT3L_ENA_SHIFT: + case MADERA_OUT3R_ENA_SHIFT: + priv->out_down_pending--; + if (!priv->out_down_pending) { + msleep(priv->out_down_delay); + priv->out_down_delay = 0; + } + break; + default: + break; + } + break; + default: + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(madera_out_ev); + +int madera_hp_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + unsigned int mask = 1 << w->shift; + unsigned int out_num = w->shift / 2; + unsigned int val; + unsigned int ep_sel = 0; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + val = mask; + break; + case SND_SOC_DAPM_PRE_PMD: + val = 0; + break; + case SND_SOC_DAPM_PRE_PMU: + case SND_SOC_DAPM_POST_PMD: + return madera_out_ev(w, kcontrol, event); + default: + return 0; + } + + /* Store the desired state for the HP outputs */ + madera->hp_ena &= ~mask; + madera->hp_ena |= val; + + /* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */ + regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel); + ep_sel &= MADERA_EP_SEL_MASK; + + /* Force off if HPDET has disabled the clamp for this output */ + if (!ep_sel && + (!madera->out_clamp[out_num] || madera->out_shorted[out_num])) + val = 0; + + regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, mask, val); + + return madera_out_ev(w, kcontrol, event); +} +EXPORT_SYMBOL_GPL(madera_hp_ev); + +int madera_anc_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + unsigned int val; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + val = 1 << w->shift; + break; + case SND_SOC_DAPM_PRE_PMD: + val = 1 << (w->shift + 1); + break; + default: + return 0; + } + + snd_soc_component_write(component, MADERA_CLOCK_CONTROL, val); + + return 0; +} +EXPORT_SYMBOL_GPL(madera_anc_ev); + +static const unsigned int madera_opclk_ref_48k_rates[] = { + 6144000, + 12288000, + 24576000, + 49152000, +}; + +static const unsigned int madera_opclk_ref_44k1_rates[] = { + 5644800, + 11289600, + 22579200, + 45158400, +}; + +static int madera_set_opclk(struct snd_soc_component *component, + unsigned int clk, unsigned int freq) +{ + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + unsigned int mask = MADERA_OPCLK_DIV_MASK | MADERA_OPCLK_SEL_MASK; + unsigned int reg, val; + const unsigned int *rates; + int ref, div, refclk; + + BUILD_BUG_ON(ARRAY_SIZE(madera_opclk_ref_48k_rates) != + ARRAY_SIZE(madera_opclk_ref_44k1_rates)); + + switch (clk) { + case MADERA_CLK_OPCLK: + reg = MADERA_OUTPUT_SYSTEM_CLOCK; + refclk = priv->sysclk; + break; + case MADERA_CLK_ASYNC_OPCLK: + reg = MADERA_OUTPUT_ASYNC_CLOCK; + refclk = priv->asyncclk; + break; + default: + return -EINVAL; + } + + if (refclk % 4000) + rates = madera_opclk_ref_44k1_rates; + else + rates = madera_opclk_ref_48k_rates; + + for (ref = 0; ref < ARRAY_SIZE(madera_opclk_ref_48k_rates); ++ref) { + if (rates[ref] > refclk) + continue; + + div = 2; + while ((rates[ref] / div >= freq) && (div <= 30)) { + if (rates[ref] / div == freq) { + dev_dbg(component->dev, "Configured %dHz OPCLK\n", + freq); + + val = (div << MADERA_OPCLK_DIV_SHIFT) | ref; + + snd_soc_component_update_bits(component, reg, + mask, val); + return 0; + } + div += 2; + } + } + + dev_err(component->dev, "Unable to generate %dHz OPCLK\n", freq); + + return -EINVAL; +} + +static int madera_get_sysclk_setting(unsigned int freq) +{ + switch (freq) { + case 0: + case 5644800: + case 6144000: + return 0; + case 11289600: + case 12288000: + return MADERA_SYSCLK_12MHZ << MADERA_SYSCLK_FREQ_SHIFT; + case 22579200: + case 24576000: + return MADERA_SYSCLK_24MHZ << MADERA_SYSCLK_FREQ_SHIFT; + case 45158400: + case 49152000: + return MADERA_SYSCLK_49MHZ << MADERA_SYSCLK_FREQ_SHIFT; + case 90316800: + case 98304000: + return MADERA_SYSCLK_98MHZ << MADERA_SYSCLK_FREQ_SHIFT; + default: + return -EINVAL; + } +} + +static int madera_get_legacy_dspclk_setting(struct madera *madera, + unsigned int freq) +{ + switch (freq) { + case 0: + return 0; + case 45158400: + case 49152000: + switch (madera->type) { + case CS47L85: + case WM1840: + if (madera->rev < 3) + return -EINVAL; + else + return MADERA_SYSCLK_49MHZ << + MADERA_SYSCLK_FREQ_SHIFT; + default: + return -EINVAL; + } + case 135475200: + case 147456000: + return MADERA_DSPCLK_147MHZ << MADERA_DSP_CLK_FREQ_LEGACY_SHIFT; + default: + return -EINVAL; + } +} + +static int madera_get_dspclk_setting(struct madera *madera, + unsigned int freq, + unsigned int *clock_2_val) +{ + switch (madera->type) { + case CS47L35: + case CS47L85: + case WM1840: + *clock_2_val = 0; /* don't use MADERA_DSP_CLOCK_2 */ + return madera_get_legacy_dspclk_setting(madera, freq); + default: + if (freq > 150000000) + return -EINVAL; + + /* Use new exact frequency control */ + *clock_2_val = freq / 15625; /* freq * (2^6) / (10^6) */ + return 0; + } +} + +int madera_set_sysclk(struct snd_soc_component *component, int clk_id, + int source, unsigned int freq, int dir) +{ + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + char *name; + unsigned int reg, clock_2_val = 0; + unsigned int mask = MADERA_SYSCLK_FREQ_MASK | MADERA_SYSCLK_SRC_MASK; + unsigned int val = source << MADERA_SYSCLK_SRC_SHIFT; + int clk_freq_sel, *clk; + int ret = 0; + + switch (clk_id) { + case MADERA_CLK_SYSCLK_1: + name = "SYSCLK"; + reg = MADERA_SYSTEM_CLOCK_1; + clk = &priv->sysclk; + clk_freq_sel = madera_get_sysclk_setting(freq); + mask |= MADERA_SYSCLK_FRAC; + break; + case MADERA_CLK_ASYNCCLK_1: + name = "ASYNCCLK"; + reg = MADERA_ASYNC_CLOCK_1; + clk = &priv->asyncclk; + clk_freq_sel = madera_get_sysclk_setting(freq); + break; + case MADERA_CLK_DSPCLK: + name = "DSPCLK"; + reg = MADERA_DSP_CLOCK_1; + clk = &priv->dspclk; + clk_freq_sel = madera_get_dspclk_setting(madera, freq, + &clock_2_val); + break; + case MADERA_CLK_OPCLK: + case MADERA_CLK_ASYNC_OPCLK: + return madera_set_opclk(component, clk_id, freq); + default: + return -EINVAL; + } + + if (clk_freq_sel < 0) { + dev_err(madera->dev, + "Failed to get clk setting for %dHZ\n", freq); + return clk_freq_sel; + } + + *clk = freq; + + if (freq == 0) { + dev_dbg(madera->dev, "%s cleared\n", name); + return 0; + } + + val |= clk_freq_sel; + + if (clock_2_val) { + ret = regmap_write(madera->regmap, MADERA_DSP_CLOCK_2, + clock_2_val); + if (ret) { + dev_err(madera->dev, + "Failed to write DSP_CONFIG2: %d\n", ret); + return ret; + } + + /* + * We're using the frequency setting in MADERA_DSP_CLOCK_2 so + * don't change the frequency select bits in MADERA_DSP_CLOCK_1 + */ + mask = MADERA_SYSCLK_SRC_MASK; + } + + if (freq % 6144000) + val |= MADERA_SYSCLK_FRAC; + + dev_dbg(madera->dev, "%s set to %uHz\n", name, freq); + + return regmap_update_bits(madera->regmap, reg, mask, val); +} +EXPORT_SYMBOL_GPL(madera_set_sysclk); + +static int madera_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + int lrclk, bclk, mode, base; + + base = dai->driver->base; + + lrclk = 0; + bclk = 0; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + mode = MADERA_FMT_DSP_MODE_A; + break; + case SND_SOC_DAIFMT_DSP_B: + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != + SND_SOC_DAIFMT_CBM_CFM) { + madera_aif_err(dai, "DSP_B not valid in slave mode\n"); + return -EINVAL; + } + mode = MADERA_FMT_DSP_MODE_B; + break; + case SND_SOC_DAIFMT_I2S: + mode = MADERA_FMT_I2S_MODE; + break; + case SND_SOC_DAIFMT_LEFT_J: + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != + SND_SOC_DAIFMT_CBM_CFM) { + madera_aif_err(dai, "LEFT_J not valid in slave mode\n"); + return -EINVAL; + } + mode = MADERA_FMT_LEFT_JUSTIFIED_MODE; + break; + default: + madera_aif_err(dai, "Unsupported DAI format %d\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + case SND_SOC_DAIFMT_CBS_CFM: + lrclk |= MADERA_AIF1TX_LRCLK_MSTR; + break; + case SND_SOC_DAIFMT_CBM_CFS: + bclk |= MADERA_AIF1_BCLK_MSTR; + break; + case SND_SOC_DAIFMT_CBM_CFM: + bclk |= MADERA_AIF1_BCLK_MSTR; + lrclk |= MADERA_AIF1TX_LRCLK_MSTR; + break; + default: + madera_aif_err(dai, "Unsupported master mode %d\n", + fmt & SND_SOC_DAIFMT_MASTER_MASK); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + bclk |= MADERA_AIF1_BCLK_INV; + lrclk |= MADERA_AIF1TX_LRCLK_INV; + break; + case SND_SOC_DAIFMT_IB_NF: + bclk |= MADERA_AIF1_BCLK_INV; + break; + case SND_SOC_DAIFMT_NB_IF: + lrclk |= MADERA_AIF1TX_LRCLK_INV; + break; + default: + madera_aif_err(dai, "Unsupported invert mode %d\n", + fmt & SND_SOC_DAIFMT_INV_MASK); + return -EINVAL; + } + + regmap_update_bits(madera->regmap, base + MADERA_AIF_BCLK_CTRL, + MADERA_AIF1_BCLK_INV | MADERA_AIF1_BCLK_MSTR, + bclk); + regmap_update_bits(madera->regmap, base + MADERA_AIF_TX_PIN_CTRL, + MADERA_AIF1TX_LRCLK_INV | MADERA_AIF1TX_LRCLK_MSTR, + lrclk); + regmap_update_bits(madera->regmap, base + MADERA_AIF_RX_PIN_CTRL, + MADERA_AIF1RX_LRCLK_INV | MADERA_AIF1RX_LRCLK_MSTR, + lrclk); + regmap_update_bits(madera->regmap, base + MADERA_AIF_FORMAT, + MADERA_AIF1_FMT_MASK, mode); + + return 0; +} + +static const int madera_48k_bclk_rates[] = { + -1, + 48000, + 64000, + 96000, + 128000, + 192000, + 256000, + 384000, + 512000, + 768000, + 1024000, + 1536000, + 2048000, + 3072000, + 4096000, + 6144000, + 8192000, + 12288000, + 24576000, +}; + +static const int madera_44k1_bclk_rates[] = { + -1, + 44100, + 58800, + 88200, + 117600, + 177640, + 235200, + 352800, + 470400, + 705600, + 940800, + 1411200, + 1881600, + 2822400, + 3763200, + 5644800, + 7526400, + 11289600, + 22579200, +}; + +static const unsigned int madera_sr_vals[] = { + 0, + 12000, + 24000, + 48000, + 96000, + 192000, + 384000, + 768000, + 0, + 11025, + 22050, + 44100, + 88200, + 176400, + 352800, + 705600, + 4000, + 8000, + 16000, + 32000, + 64000, + 128000, + 256000, + 512000, +}; + +#define MADERA_192K_48K_RATE_MASK 0x0F003E +#define MADERA_192K_44K1_RATE_MASK 0x003E00 +#define MADERA_192K_RATE_MASK (MADERA_192K_48K_RATE_MASK | \ + MADERA_192K_44K1_RATE_MASK) + +static const struct snd_pcm_hw_constraint_list madera_constraint = { + .count = ARRAY_SIZE(madera_sr_vals), + .list = madera_sr_vals, +}; + +static int madera_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1]; + unsigned int base_rate; + + if (!substream->runtime) + return 0; + + switch (dai_priv->clk) { + case MADERA_CLK_SYSCLK_1: + case MADERA_CLK_SYSCLK_2: + case MADERA_CLK_SYSCLK_3: + base_rate = priv->sysclk; + break; + case MADERA_CLK_ASYNCCLK_1: + case MADERA_CLK_ASYNCCLK_2: + base_rate = priv->asyncclk; + break; + default: + return 0; + } + + if (base_rate == 0) + dai_priv->constraint.mask = MADERA_192K_RATE_MASK; + else if (base_rate % 4000) + dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK; + else + dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK; + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &dai_priv->constraint); +} + +static int madera_hw_params_rate(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1]; + int base = dai->driver->base; + int i, sr_val; + unsigned int reg, cur, tar; + int ret; + + for (i = 0; i < ARRAY_SIZE(madera_sr_vals); i++) + if (madera_sr_vals[i] == params_rate(params)) + break; + + if (i == ARRAY_SIZE(madera_sr_vals)) { + madera_aif_err(dai, "Unsupported sample rate %dHz\n", + params_rate(params)); + return -EINVAL; + } + sr_val = i; + + switch (dai_priv->clk) { + case MADERA_CLK_SYSCLK_1: + reg = MADERA_SAMPLE_RATE_1; + tar = 0 << MADERA_AIF1_RATE_SHIFT; + break; + case MADERA_CLK_SYSCLK_2: + reg = MADERA_SAMPLE_RATE_2; + tar = 1 << MADERA_AIF1_RATE_SHIFT; + break; + case MADERA_CLK_SYSCLK_3: + reg = MADERA_SAMPLE_RATE_3; + tar = 2 << MADERA_AIF1_RATE_SHIFT; + break; + case MADERA_CLK_ASYNCCLK_1: + reg = MADERA_ASYNC_SAMPLE_RATE_1, + tar = 8 << MADERA_AIF1_RATE_SHIFT; + break; + case MADERA_CLK_ASYNCCLK_2: + reg = MADERA_ASYNC_SAMPLE_RATE_2, + tar = 9 << MADERA_AIF1_RATE_SHIFT; + break; + default: + madera_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); + return -EINVAL; + } + + snd_soc_component_update_bits(component, reg, MADERA_SAMPLE_RATE_1_MASK, + sr_val); + + if (!base) + return 0; + + ret = regmap_read(priv->madera->regmap, + base + MADERA_AIF_RATE_CTRL, &cur); + if (ret != 0) { + madera_aif_err(dai, "Failed to check rate: %d\n", ret); + return ret; + } + + if ((cur & MADERA_AIF1_RATE_MASK) == (tar & MADERA_AIF1_RATE_MASK)) + return 0; + + mutex_lock(&priv->rate_lock); + + if (!madera_can_change_grp_rate(priv, base + MADERA_AIF_RATE_CTRL)) { + madera_aif_warn(dai, "Cannot change rate while active\n"); + ret = -EBUSY; + goto out; + } + + /* Guard the rate change with SYSCLK cycles */ + madera_spin_sysclk(priv); + snd_soc_component_update_bits(component, base + MADERA_AIF_RATE_CTRL, + MADERA_AIF1_RATE_MASK, tar); + madera_spin_sysclk(priv); + +out: + mutex_unlock(&priv->rate_lock); + + return ret; +} + +static int madera_aif_cfg_changed(struct snd_soc_component *component, + int base, int bclk, int lrclk, int frame) +{ + unsigned int val; + int ret; + + ret = snd_soc_component_read(component, base + MADERA_AIF_BCLK_CTRL, + &val); + if (ret) + return ret; + if (bclk != (val & MADERA_AIF1_BCLK_FREQ_MASK)) + return 1; + + ret = snd_soc_component_read(component, base + MADERA_AIF_RX_BCLK_RATE, + &val); + if (ret) + return ret; + if (lrclk != (val & MADERA_AIF1RX_BCPF_MASK)) + return 1; + + ret = snd_soc_component_read(component, base + MADERA_AIF_FRAME_CTRL_1, + &val); + if (ret) + return ret; + if (frame != (val & (MADERA_AIF1TX_WL_MASK | + MADERA_AIF1TX_SLOT_LEN_MASK))) + return 1; + + return 0; +} + +static int madera_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + int base = dai->driver->base; + const int *rates; + int i, ret; + unsigned int val; + unsigned int channels = params_channels(params); + unsigned int rate = params_rate(params); + unsigned int chan_limit = + madera->pdata.codec.max_channels_clocked[dai->id - 1]; + int tdm_width = priv->tdm_width[dai->id - 1]; + int tdm_slots = priv->tdm_slots[dai->id - 1]; + int bclk, lrclk, wl, frame, bclk_target, num_rates; + int reconfig; + unsigned int aif_tx_state = 0, aif_rx_state = 0; + + if (rate % 4000) { + rates = &madera_44k1_bclk_rates[0]; + num_rates = ARRAY_SIZE(madera_44k1_bclk_rates); + } else { + rates = &madera_48k_bclk_rates[0]; + num_rates = ARRAY_SIZE(madera_48k_bclk_rates); + } + + wl = snd_pcm_format_width(params_format(params)); + + if (tdm_slots) { + madera_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n", + tdm_slots, tdm_width); + bclk_target = tdm_slots * tdm_width * rate; + channels = tdm_slots; + } else { + bclk_target = snd_soc_params_to_bclk(params); + tdm_width = wl; + } + + if (chan_limit && chan_limit < channels) { + madera_aif_dbg(dai, "Limiting to %d channels\n", chan_limit); + bclk_target /= channels; + bclk_target *= chan_limit; + } + + /* Force multiple of 2 channels for I2S mode */ + ret = snd_soc_component_read(component, base + MADERA_AIF_FORMAT, &val); + if (ret) + return ret; + + val &= MADERA_AIF1_FMT_MASK; + if ((channels & 1) && val == MADERA_FMT_I2S_MODE) { + madera_aif_dbg(dai, "Forcing stereo mode\n"); + bclk_target /= channels; + bclk_target *= channels + 1; + } + + for (i = 0; i < num_rates; i++) { + if (rates[i] >= bclk_target && rates[i] % rate == 0) { + bclk = i; + break; + } + } + + if (i == num_rates) { + madera_aif_err(dai, "Unsupported sample rate %dHz\n", rate); + return -EINVAL; + } + + lrclk = rates[bclk] / rate; + + madera_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", + rates[bclk], rates[bclk] / lrclk); + + frame = wl << MADERA_AIF1TX_WL_SHIFT | tdm_width; + + reconfig = madera_aif_cfg_changed(component, base, bclk, lrclk, frame); + if (reconfig < 0) + return reconfig; + + if (reconfig) { + /* Save AIF TX/RX state */ + regmap_read(madera->regmap, base + MADERA_AIF_TX_ENABLES, + &aif_tx_state); + regmap_read(madera->regmap, base + MADERA_AIF_RX_ENABLES, + &aif_rx_state); + /* Disable AIF TX/RX before reconfiguring it */ + regmap_update_bits(madera->regmap, + base + MADERA_AIF_TX_ENABLES, 0xff, 0x0); + regmap_update_bits(madera->regmap, + base + MADERA_AIF_RX_ENABLES, 0xff, 0x0); + } + + ret = madera_hw_params_rate(substream, params, dai); + if (ret != 0) + goto restore_aif; + + if (reconfig) { + regmap_update_bits(madera->regmap, + base + MADERA_AIF_BCLK_CTRL, + MADERA_AIF1_BCLK_FREQ_MASK, bclk); + regmap_update_bits(madera->regmap, + base + MADERA_AIF_RX_BCLK_RATE, + MADERA_AIF1RX_BCPF_MASK, lrclk); + regmap_update_bits(madera->regmap, + base + MADERA_AIF_FRAME_CTRL_1, + MADERA_AIF1TX_WL_MASK | + MADERA_AIF1TX_SLOT_LEN_MASK, frame); + regmap_update_bits(madera->regmap, + base + MADERA_AIF_FRAME_CTRL_2, + MADERA_AIF1RX_WL_MASK | + MADERA_AIF1RX_SLOT_LEN_MASK, frame); + } + +restore_aif: + if (reconfig) { + /* Restore AIF TX/RX state */ + regmap_update_bits(madera->regmap, + base + MADERA_AIF_TX_ENABLES, + 0xff, aif_tx_state); + regmap_update_bits(madera->regmap, + base + MADERA_AIF_RX_ENABLES, + 0xff, aif_rx_state); + } + + return ret; +} + +static int madera_is_syncclk(int clk_id) +{ + switch (clk_id) { + case MADERA_CLK_SYSCLK_1: + case MADERA_CLK_SYSCLK_2: + case MADERA_CLK_SYSCLK_3: + return 1; + case MADERA_CLK_ASYNCCLK_1: + case MADERA_CLK_ASYNCCLK_2: + return 0; + default: + return -EINVAL; + } +} + +static int madera_dai_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = dai->component; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1]; + struct snd_soc_dapm_route routes[2]; + int is_sync; + + is_sync = madera_is_syncclk(clk_id); + if (is_sync < 0) { + dev_err(component->dev, "Illegal DAI clock id %d\n", clk_id); + return is_sync; + } + + if (is_sync == madera_is_syncclk(dai_priv->clk)) + return 0; + + if (dai->active) { + dev_err(component->dev, "Can't change clock on active DAI %d\n", + dai->id); + return -EBUSY; + } + + dev_dbg(component->dev, "Setting AIF%d to %s\n", dai->id, + is_sync ? "SYSCLK" : "ASYNCCLK"); + + /* + * A connection to SYSCLK is always required, we only add and remove + * a connection to ASYNCCLK + */ + memset(&routes, 0, sizeof(routes)); + routes[0].sink = dai->driver->capture.stream_name; + routes[1].sink = dai->driver->playback.stream_name; + routes[0].source = "ASYNCCLK"; + routes[1].source = "ASYNCCLK"; + + if (is_sync) + snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes)); + else + snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes)); + + dai_priv->clk = clk_id; + + return snd_soc_dapm_sync(dapm); +} + +static int madera_set_tristate(struct snd_soc_dai *dai, int tristate) +{ + struct snd_soc_component *component = dai->component; + int base = dai->driver->base; + unsigned int reg; + int ret; + + if (tristate) + reg = MADERA_AIF1_TRI; + else + reg = 0; + + ret = snd_soc_component_update_bits(component, + base + MADERA_AIF_RATE_CTRL, + MADERA_AIF1_TRI, reg); + if (ret < 0) + return ret; + else + return 0; +} + +static void madera_set_channels_to_mask(struct snd_soc_dai *dai, + unsigned int base, + int channels, unsigned int mask) +{ + struct snd_soc_component *component = dai->component; + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + int slot, i; + + for (i = 0; i < channels; ++i) { + slot = ffs(mask) - 1; + if (slot < 0) + return; + + regmap_write(madera->regmap, base + i, slot); + + mask &= ~(1 << slot); + } + + if (mask) + madera_aif_warn(dai, "Too many channels in TDM mask\n"); +} + +static int madera_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + int base = dai->driver->base; + int rx_max_chan = dai->driver->playback.channels_max; + int tx_max_chan = dai->driver->capture.channels_max; + + /* Only support TDM for the physical AIFs */ + if (dai->id > MADERA_MAX_AIF) + return -ENOTSUPP; + + if (slots == 0) { + tx_mask = (1 << tx_max_chan) - 1; + rx_mask = (1 << rx_max_chan) - 1; + } + + madera_set_channels_to_mask(dai, base + MADERA_AIF_FRAME_CTRL_3, + tx_max_chan, tx_mask); + madera_set_channels_to_mask(dai, base + MADERA_AIF_FRAME_CTRL_11, + rx_max_chan, rx_mask); + + priv->tdm_width[dai->id - 1] = slot_width; + priv->tdm_slots[dai->id - 1] = slots; + + return 0; +} + +const struct snd_soc_dai_ops madera_dai_ops = { + .startup = &madera_startup, + .set_fmt = &madera_set_fmt, + .set_tdm_slot = &madera_set_tdm_slot, + .hw_params = &madera_hw_params, + .set_sysclk = &madera_dai_set_sysclk, + .set_tristate = &madera_set_tristate, +}; +EXPORT_SYMBOL_GPL(madera_dai_ops); + +const struct snd_soc_dai_ops madera_simple_dai_ops = { + .startup = &madera_startup, + .hw_params = &madera_hw_params_rate, + .set_sysclk = &madera_dai_set_sysclk, +}; +EXPORT_SYMBOL_GPL(madera_simple_dai_ops); + +int madera_init_dai(struct madera_priv *priv, int id) +{ + struct madera_dai_priv *dai_priv = &priv->dai[id]; + + dai_priv->clk = MADERA_CLK_SYSCLK_1; + dai_priv->constraint = madera_constraint; + + return 0; +} +EXPORT_SYMBOL_GPL(madera_init_dai); + +static const struct { + unsigned int min; + unsigned int max; + u16 fratio; + int ratio; +} fll_sync_fratios[] = { + { 0, 64000, 4, 16 }, + { 64000, 128000, 3, 8 }, + { 128000, 256000, 2, 4 }, + { 256000, 1000000, 1, 2 }, + { 1000000, 13500000, 0, 1 }, +}; + +static const unsigned int pseudo_fref_max[MADERA_FLL_MAX_FRATIO] = { + 13500000, + 6144000, + 6144000, + 3072000, + 3072000, + 2822400, + 2822400, + 1536000, + 1536000, + 1536000, + 1536000, + 1536000, + 1536000, + 1536000, + 1536000, + 768000, +}; + +struct madera_fll_gains { + unsigned int min; + unsigned int max; + int gain; /* main gain */ + int alt_gain; /* alternate integer gain */ +}; + +static const struct madera_fll_gains madera_fll_sync_gains[] = { + { 0, 256000, 0, -1 }, + { 256000, 1000000, 2, -1 }, + { 1000000, 13500000, 4, -1 }, +}; + +static const struct madera_fll_gains madera_fll_main_gains[] = { + { 0, 100000, 0, 2 }, + { 100000, 375000, 2, 2 }, + { 375000, 768000, 3, 2 }, + { 768001, 1500000, 3, 3 }, + { 1500000, 6000000, 4, 3 }, + { 6000000, 13500000, 5, 3 }, +}; + +static int madera_find_sync_fratio(unsigned int fref, int *fratio) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fll_sync_fratios); i++) { + if (fll_sync_fratios[i].min <= fref && + fref <= fll_sync_fratios[i].max) { + if (fratio) + *fratio = fll_sync_fratios[i].fratio; + + return fll_sync_fratios[i].ratio; + } + } + + return -EINVAL; +} + +static int madera_find_main_fratio(unsigned int fref, unsigned int fout, + int *fratio) +{ + int ratio = 1; + + while ((fout / (ratio * fref)) > MADERA_FLL_MAX_N) + ratio++; + + if (fratio) + *fratio = ratio - 1; + + return ratio; +} + +static int madera_find_fratio(struct madera_fll *fll, unsigned int fref, + bool sync, int *fratio) +{ + switch (fll->madera->type) { + case CS47L35: + switch (fll->madera->rev) { + case 0: + /* rev A0 uses sync calculation for both loops */ + return madera_find_sync_fratio(fref, fratio); + default: + if (sync) + return madera_find_sync_fratio(fref, fratio); + else + return madera_find_main_fratio(fref, + fll->fout, + fratio); + } + break; + case CS47L85: + case WM1840: + /* these use the same calculation for main and sync loops */ + return madera_find_sync_fratio(fref, fratio); + default: + if (sync) + return madera_find_sync_fratio(fref, fratio); + else + return madera_find_main_fratio(fref, fll->fout, fratio); + } +} + +static int madera_calc_fratio(struct madera_fll *fll, + struct madera_fll_cfg *cfg, + unsigned int fref, bool sync) +{ + int init_ratio, ratio; + int refdiv, div; + + /* fref must be <=13.5MHz, find initial refdiv */ + div = 1; + cfg->refdiv = 0; + while (fref > MADERA_FLL_MAX_FREF) { + div *= 2; + fref /= 2; + cfg->refdiv++; + + if (div > MADERA_FLL_MAX_REFDIV) + return -EINVAL; + } + + /* Find an appropriate FLL_FRATIO */ + init_ratio = madera_find_fratio(fll, fref, sync, &cfg->fratio); + if (init_ratio < 0) { + madera_fll_err(fll, "Unable to find FRATIO for fref=%uHz\n", + fref); + return init_ratio; + } + + if (!sync) + cfg->fratio = init_ratio - 1; + + switch (fll->madera->type) { + case CS47L35: + switch (fll->madera->rev) { + case 0: + if (sync) + return init_ratio; + break; + default: + return init_ratio; + } + break; + case CS47L85: + case WM1840: + if (sync) + return init_ratio; + break; + default: + return init_ratio; + } + + /* + * For CS47L35 rev A0, CS47L85 and WM1840 adjust FRATIO/refdiv to avoid + * integer mode if possible + */ + refdiv = cfg->refdiv; + + while (div <= MADERA_FLL_MAX_REFDIV) { + /* + * start from init_ratio because this may already give a + * fractional N.K + */ + for (ratio = init_ratio; ratio > 0; ratio--) { + if (fll->fout % (ratio * fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + return ratio; + } + } + + for (ratio = init_ratio + 1; ratio <= MADERA_FLL_MAX_FRATIO; + ratio++) { + if ((MADERA_FLL_VCO_CORNER / 2) / + (MADERA_FLL_VCO_MULT * ratio) < fref) + break; + + if (fref > pseudo_fref_max[ratio - 1]) + break; + + if (fll->fout % (ratio * fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + return ratio; + } + } + + div *= 2; + fref /= 2; + refdiv++; + init_ratio = madera_find_fratio(fll, fref, sync, NULL); + } + + madera_fll_warn(fll, "Falling back to integer mode operation\n"); + + return cfg->fratio + 1; +} + +static int madera_find_fll_gain(struct madera_fll *fll, + struct madera_fll_cfg *cfg, + unsigned int fref, + const struct madera_fll_gains *gains, + int n_gains) +{ + int i; + + for (i = 0; i < n_gains; i++) { + if (gains[i].min <= fref && fref <= gains[i].max) { + cfg->gain = gains[i].gain; + cfg->alt_gain = gains[i].alt_gain; + return 0; + } + } + + madera_fll_err(fll, "Unable to find gain for fref=%uHz\n", fref); + + return -EINVAL; +} + +static int madera_calc_fll(struct madera_fll *fll, + struct madera_fll_cfg *cfg, + unsigned int fref, bool sync) +{ + unsigned int gcd_fll; + const struct madera_fll_gains *gains; + int n_gains; + int ratio, ret; + + madera_fll_dbg(fll, "fref=%u Fout=%u fvco=%u\n", + fref, fll->fout, fll->fout * MADERA_FLL_VCO_MULT); + + /* Find an appropriate FLL_FRATIO and refdiv */ + ratio = madera_calc_fratio(fll, cfg, fref, sync); + if (ratio < 0) + return ratio; + + /* Apply the division for our remaining calculations */ + fref = fref / (1 << cfg->refdiv); + + cfg->n = fll->fout / (ratio * fref); + + if (fll->fout % (ratio * fref)) { + gcd_fll = gcd(fll->fout, ratio * fref); + madera_fll_dbg(fll, "GCD=%u\n", gcd_fll); + + cfg->theta = (fll->fout - (cfg->n * ratio * fref)) + / gcd_fll; + cfg->lambda = (ratio * fref) / gcd_fll; + } else { + cfg->theta = 0; + cfg->lambda = 0; + } + + /* + * Round down to 16bit range with cost of accuracy lost. + * Denominator must be bigger than numerator so we only + * take care of it. + */ + while (cfg->lambda >= (1 << 16)) { + cfg->theta >>= 1; + cfg->lambda >>= 1; + } + + switch (fll->madera->type) { + case CS47L35: + switch (fll->madera->rev) { + case 0: + /* Rev A0 uses the sync gains for both loops */ + gains = madera_fll_sync_gains; + n_gains = ARRAY_SIZE(madera_fll_sync_gains); + break; + default: + if (sync) { + gains = madera_fll_sync_gains; + n_gains = ARRAY_SIZE(madera_fll_sync_gains); + } else { + gains = madera_fll_main_gains; + n_gains = ARRAY_SIZE(madera_fll_main_gains); + } + break; + } + break; + case CS47L85: + case WM1840: + /* These use the sync gains for both loops */ + gains = madera_fll_sync_gains; + n_gains = ARRAY_SIZE(madera_fll_sync_gains); + break; + default: + if (sync) { + gains = madera_fll_sync_gains; + n_gains = ARRAY_SIZE(madera_fll_sync_gains); + } else { + gains = madera_fll_main_gains; + n_gains = ARRAY_SIZE(madera_fll_main_gains); + } + break; + } + + ret = madera_find_fll_gain(fll, cfg, fref, gains, n_gains); + if (ret) + return ret; + + madera_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n", + cfg->n, cfg->theta, cfg->lambda); + madera_fll_dbg(fll, "FRATIO=0x%x(%d) REFCLK_DIV=0x%x(%d)\n", + cfg->fratio, ratio, cfg->refdiv, 1 << cfg->refdiv); + madera_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain); + + return 0; +} + +static bool madera_write_fll(struct madera *madera, unsigned int base, + struct madera_fll_cfg *cfg, int source, + bool sync, int gain) +{ + bool change, fll_change; + + fll_change = false; + regmap_update_bits_check(madera->regmap, + base + MADERA_FLL_CONTROL_3_OFFS, + MADERA_FLL1_THETA_MASK, + cfg->theta, &change); + fll_change |= change; + regmap_update_bits_check(madera->regmap, + base + MADERA_FLL_CONTROL_4_OFFS, + MADERA_FLL1_LAMBDA_MASK, + cfg->lambda, &change); + fll_change |= change; + regmap_update_bits_check(madera->regmap, + base + MADERA_FLL_CONTROL_5_OFFS, + MADERA_FLL1_FRATIO_MASK, + cfg->fratio << MADERA_FLL1_FRATIO_SHIFT, + &change); + fll_change |= change; + regmap_update_bits_check(madera->regmap, + base + MADERA_FLL_CONTROL_6_OFFS, + MADERA_FLL1_REFCLK_DIV_MASK | + MADERA_FLL1_REFCLK_SRC_MASK, + cfg->refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT | + source << MADERA_FLL1_REFCLK_SRC_SHIFT, + &change); + fll_change |= change; + + if (sync) { + regmap_update_bits_check(madera->regmap, + base + MADERA_FLL_SYNCHRONISER_7_OFFS, + MADERA_FLL1_GAIN_MASK, + gain << MADERA_FLL1_GAIN_SHIFT, + &change); + fll_change |= change; + } else { + regmap_update_bits_check(madera->regmap, + base + MADERA_FLL_CONTROL_7_OFFS, + MADERA_FLL1_GAIN_MASK, + gain << MADERA_FLL1_GAIN_SHIFT, + &change); + fll_change |= change; + } + + regmap_update_bits_check(madera->regmap, + base + MADERA_FLL_CONTROL_2_OFFS, + MADERA_FLL1_CTRL_UPD | MADERA_FLL1_N_MASK, + MADERA_FLL1_CTRL_UPD | cfg->n, &change); + fll_change |= change; + + return fll_change; +} + +static int madera_is_enabled_fll(struct madera_fll *fll, int base) +{ + struct madera *madera = fll->madera; + unsigned int reg; + int ret; + + ret = regmap_read(madera->regmap, + base + MADERA_FLL_CONTROL_1_OFFS, ®); + if (ret != 0) { + madera_fll_err(fll, "Failed to read current state: %d\n", ret); + return ret; + } + + return reg & MADERA_FLL1_ENA; +} + +static int madera_wait_for_fll(struct madera_fll *fll, bool requested) +{ + struct madera *madera = fll->madera; + unsigned int val = 0; + bool status; + int i; + + madera_fll_dbg(fll, "Waiting for FLL...\n"); + + for (i = 0; i < 30; i++) { + regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_2, &val); + status = val & (MADERA_FLL1_LOCK_STS1 << (fll->id - 1)); + if (status == requested) + return 0; + + switch (i) { + case 0 ... 5: + usleep_range(75, 125); + break; + case 11 ... 20: + usleep_range(750, 1250); + break; + default: + msleep(20); + break; + } + } + + madera_fll_warn(fll, "Timed out waiting for lock\n"); + + return -ETIMEDOUT; +} + +static bool madera_set_fll_phase_integrator(struct madera_fll *fll, + struct madera_fll_cfg *ref_cfg, + bool sync) +{ + unsigned int val; + bool reg_change; + + if (!sync && ref_cfg->theta == 0) + val = (1 << MADERA_FLL1_PHASE_ENA_SHIFT) | + (2 << MADERA_FLL1_PHASE_GAIN_SHIFT); + else + val = 2 << MADERA_FLL1_PHASE_GAIN_SHIFT; + + regmap_update_bits_check(fll->madera->regmap, + fll->base + MADERA_FLL_EFS_2_OFFS, + MADERA_FLL1_PHASE_ENA_MASK | + MADERA_FLL1_PHASE_GAIN_MASK, + val, ®_change); + + return reg_change; +} + +static void madera_disable_fll(struct madera_fll *fll) +{ + struct madera *madera = fll->madera; + unsigned int sync_base; + bool change; + + switch (madera->type) { + case CS47L35: + sync_base = fll->base + CS47L35_FLL_SYNCHRONISER_OFFS; + break; + default: + sync_base = fll->base + MADERA_FLL_SYNCHRONISER_OFFS; + break; + } + + madera_fll_dbg(fll, "Disabling FLL\n"); + + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_FREERUN, MADERA_FLL1_FREERUN); + regmap_update_bits_check(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_ENA, 0, &change); + regmap_update_bits(madera->regmap, + sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS, + MADERA_FLL1_SYNC_ENA, 0); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_FREERUN, 0); + + madera_wait_for_fll(fll, false); + + if (change) + pm_runtime_put_autosuspend(madera->dev); +} + +static int madera_enable_fll(struct madera_fll *fll) +{ + struct madera *madera = fll->madera; + bool have_sync = false; + int already_enabled = madera_is_enabled_fll(fll, fll->base); + int sync_enabled; + struct madera_fll_cfg cfg; + unsigned int sync_base; + int gain, ret; + bool fll_change = false; + + if (already_enabled < 0) + return already_enabled; /* error getting current state */ + + if (fll->ref_src < 0 || fll->ref_freq == 0) { + madera_fll_err(fll, "No REFCLK\n"); + ret = -EINVAL; + goto err; + } + + madera_fll_dbg(fll, "Enabling FLL, initially %s\n", + already_enabled ? "enabled" : "disabled"); + + if (fll->fout < MADERA_FLL_MIN_FOUT || + fll->fout > MADERA_FLL_MAX_FOUT) { + madera_fll_err(fll, "invalid fout %uHz\n", fll->fout); + ret = -EINVAL; + goto err; + } + + switch (madera->type) { + case CS47L35: + sync_base = fll->base + CS47L35_FLL_SYNCHRONISER_OFFS; + break; + default: + sync_base = fll->base + MADERA_FLL_SYNCHRONISER_OFFS; + break; + } + + sync_enabled = madera_is_enabled_fll(fll, sync_base); + if (sync_enabled < 0) + return sync_enabled; + + if (already_enabled) { + /* Facilitate smooth refclk across the transition */ + regmap_update_bits(fll->madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_FREERUN, + MADERA_FLL1_FREERUN); + udelay(32); + regmap_update_bits(fll->madera->regmap, + fll->base + MADERA_FLL_CONTROL_7_OFFS, + MADERA_FLL1_GAIN_MASK, 0); + } + + /* Apply SYNCCLK setting */ + if (fll->sync_src >= 0) { + ret = madera_calc_fll(fll, &cfg, fll->sync_freq, true); + if (ret < 0) + goto err; + + fll_change |= madera_write_fll(madera, sync_base, + &cfg, fll->sync_src, + true, cfg.gain); + have_sync = true; + } + + if (already_enabled && !!sync_enabled != have_sync) + madera_fll_warn(fll, "Synchroniser changed on active FLL\n"); + + /* Apply REFCLK setting */ + ret = madera_calc_fll(fll, &cfg, fll->ref_freq, false); + if (ret < 0) + goto err; + + /* Ref path hardcodes lambda to 65536 when sync is on */ + if (have_sync && cfg.lambda) + cfg.theta = (cfg.theta * (1 << 16)) / cfg.lambda; + + switch (fll->madera->type) { + case CS47L35: + switch (fll->madera->rev) { + case 0: + gain = cfg.gain; + break; + default: + fll_change |= + madera_set_fll_phase_integrator(fll, &cfg, + have_sync); + if (!have_sync && cfg.theta == 0) + gain = cfg.alt_gain; + else + gain = cfg.gain; + break; + } + break; + case CS47L85: + case WM1840: + gain = cfg.gain; + break; + default: + fll_change |= madera_set_fll_phase_integrator(fll, &cfg, + have_sync); + if (!have_sync && cfg.theta == 0) + gain = cfg.alt_gain; + else + gain = cfg.gain; + break; + } + + fll_change |= madera_write_fll(madera, fll->base, + &cfg, fll->ref_src, + false, gain); + + /* + * Increase the bandwidth if we're not using a low frequency + * sync source. + */ + if (have_sync && fll->sync_freq > 100000) + regmap_update_bits(madera->regmap, + sync_base + MADERA_FLL_SYNCHRONISER_7_OFFS, + MADERA_FLL1_SYNC_DFSAT_MASK, 0); + else + regmap_update_bits(madera->regmap, + sync_base + MADERA_FLL_SYNCHRONISER_7_OFFS, + MADERA_FLL1_SYNC_DFSAT_MASK, + MADERA_FLL1_SYNC_DFSAT); + + if (!already_enabled) + pm_runtime_get_sync(madera->dev); + + if (have_sync) + regmap_update_bits(madera->regmap, + sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS, + MADERA_FLL1_SYNC_ENA, + MADERA_FLL1_SYNC_ENA); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_ENA, MADERA_FLL1_ENA); + + if (already_enabled) + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_FREERUN, 0); + + if (fll_change || !already_enabled) + madera_wait_for_fll(fll, true); + + return 0; + +err: + /* In case of error don't leave the FLL running with an old config */ + madera_disable_fll(fll); + + return ret; +} + +static int madera_apply_fll(struct madera_fll *fll) +{ + if (fll->fout) { + return madera_enable_fll(fll); + } else { + madera_disable_fll(fll); + return 0; + } +} + +int madera_set_fll_syncclk(struct madera_fll *fll, int source, + unsigned int fref, unsigned int fout) +{ + /* + * fout is ignored, since the synchronizer is an optional extra + * constraint on the Fout generated from REFCLK, so the Fout is + * set when configuring REFCLK + */ + + if (fll->sync_src == source && fll->sync_freq == fref) + return 0; + + fll->sync_src = source; + fll->sync_freq = fref; + + return madera_apply_fll(fll); +} +EXPORT_SYMBOL_GPL(madera_set_fll_syncclk); + +int madera_set_fll_refclk(struct madera_fll *fll, int source, + unsigned int fref, unsigned int fout) +{ + int ret; + + if (fll->ref_src == source && + fll->ref_freq == fref && fll->fout == fout) + return 0; + + /* + * Changes of fout on an enabled FLL aren't allowed except when + * setting fout==0 to disable the FLL + */ + if (fout && fout != fll->fout) { + ret = madera_is_enabled_fll(fll, fll->base); + if (ret < 0) + return ret; + + if (ret) { + madera_fll_err(fll, "Can't change Fout on active FLL\n"); + return -EBUSY; + } + } + + fll->ref_src = source; + fll->ref_freq = fref; + fll->fout = fout; + + return madera_apply_fll(fll); +} +EXPORT_SYMBOL_GPL(madera_set_fll_refclk); + +int madera_init_fll(struct madera *madera, int id, int base, + struct madera_fll *fll) +{ + fll->id = id; + fll->base = base; + fll->madera = madera; + fll->ref_src = MADERA_FLL_SRC_NONE; + fll->sync_src = MADERA_FLL_SRC_NONE; + + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_FREERUN, 0); + + return 0; +} +EXPORT_SYMBOL_GPL(madera_init_fll); + +static const struct reg_sequence madera_fll_ao_32K_49M_patch[] = { + { MADERA_FLLAO_CONTROL_2, 0x02EE }, + { MADERA_FLLAO_CONTROL_3, 0x0000 }, + { MADERA_FLLAO_CONTROL_4, 0x0001 }, + { MADERA_FLLAO_CONTROL_5, 0x0002 }, + { MADERA_FLLAO_CONTROL_6, 0x8001 }, + { MADERA_FLLAO_CONTROL_7, 0x0004 }, + { MADERA_FLLAO_CONTROL_8, 0x0077 }, + { MADERA_FLLAO_CONTROL_10, 0x06D8 }, + { MADERA_FLLAO_CONTROL_11, 0x0085 }, + { MADERA_FLLAO_CONTROL_2, 0x82EE }, +}; + +static const struct reg_sequence madera_fll_ao_32K_45M_patch[] = { + { MADERA_FLLAO_CONTROL_2, 0x02B1 }, + { MADERA_FLLAO_CONTROL_3, 0x0001 }, + { MADERA_FLLAO_CONTROL_4, 0x0010 }, + { MADERA_FLLAO_CONTROL_5, 0x0002 }, + { MADERA_FLLAO_CONTROL_6, 0x8001 }, + { MADERA_FLLAO_CONTROL_7, 0x0004 }, + { MADERA_FLLAO_CONTROL_8, 0x0077 }, + { MADERA_FLLAO_CONTROL_10, 0x06D8 }, + { MADERA_FLLAO_CONTROL_11, 0x0005 }, + { MADERA_FLLAO_CONTROL_2, 0x82B1 }, +}; + +struct madera_fllao_patch { + unsigned int fin; + unsigned int fout; + const struct reg_sequence *patch; + unsigned int patch_size; +}; + +static const struct madera_fllao_patch madera_fllao_settings[] = { + { + .fin = 32768, + .fout = 49152000, + .patch = madera_fll_ao_32K_49M_patch, + .patch_size = ARRAY_SIZE(madera_fll_ao_32K_49M_patch), + + }, + { + .fin = 32768, + .fout = 45158400, + .patch = madera_fll_ao_32K_45M_patch, + .patch_size = ARRAY_SIZE(madera_fll_ao_32K_45M_patch), + }, +}; + +static int madera_enable_fll_ao(struct madera_fll *fll, + const struct reg_sequence *patch, + unsigned int patch_size) +{ + struct madera *madera = fll->madera; + int already_enabled = madera_is_enabled_fll(fll, fll->base); + unsigned int val; + int i; + + if (already_enabled < 0) + return already_enabled; + + if (!already_enabled) + pm_runtime_get_sync(madera->dev); + + madera_fll_dbg(fll, "Enabling FLL_AO, initially %s\n", + already_enabled ? "enabled" : "disabled"); + + /* FLL_AO_HOLD must be set before configuring any registers */ + regmap_update_bits(fll->madera->regmap, + fll->base + MADERA_FLLAO_CONTROL_1_OFFS, + MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD); + + for (i = 0; i < patch_size; i++) { + val = patch[i].def; + + /* modify the patch to apply fll->ref_src as input clock */ + if (patch[i].reg == MADERA_FLLAO_CONTROL_6) { + val &= ~MADERA_FLL_AO_REFCLK_SRC_MASK; + val |= (fll->ref_src << MADERA_FLL_AO_REFCLK_SRC_SHIFT) + & MADERA_FLL_AO_REFCLK_SRC_MASK; + } + + regmap_write(madera->regmap, patch[i].reg, val); + } + + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLLAO_CONTROL_1_OFFS, + MADERA_FLL_AO_ENA, MADERA_FLL_AO_ENA); + + /* Release the hold so that fll_ao locks to external frequency */ + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLLAO_CONTROL_1_OFFS, + MADERA_FLL_AO_HOLD, 0); + + if (!already_enabled) + madera_wait_for_fll(fll, true); + + return 0; +} + +static int madera_disable_fll_ao(struct madera_fll *fll) +{ + struct madera *madera = fll->madera; + bool change; + + madera_fll_dbg(fll, "Disabling FLL_AO\n"); + + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLLAO_CONTROL_1_OFFS, + MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD); + regmap_update_bits_check(madera->regmap, + fll->base + MADERA_FLLAO_CONTROL_1_OFFS, + MADERA_FLL_AO_ENA, 0, &change); + + madera_wait_for_fll(fll, false); + + /* + * ctrl_up gates the writes to all fll_ao register, setting it to 0 + * here ensures that after a runtime suspend/resume cycle when one + * enables the fllao then ctrl_up is the last bit that is configured + * by the fllao enable code rather than the cache sync operation which + * would have updated it much earlier before writing out all fllao + * registers + */ + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLLAO_CONTROL_2_OFFS, + MADERA_FLL_AO_CTRL_UPD_MASK, 0); + + if (change) + pm_runtime_put_autosuspend(madera->dev); + + return 0; +} + +int madera_set_fll_ao_refclk(struct madera_fll *fll, int source, + unsigned int fin, unsigned int fout) +{ + int ret = 0; + const struct reg_sequence *patch = NULL; + int patch_size = 0; + unsigned int i; + + if (fll->ref_src == source && + fll->ref_freq == fin && fll->fout == fout) + return 0; + + madera_fll_dbg(fll, "Change FLL_AO refclk to fin=%u fout=%u source=%d\n", + fin, fout, source); + + if (fout && (fll->ref_freq != fin || fll->fout != fout)) { + for (i = 0; i < ARRAY_SIZE(madera_fllao_settings); i++) { + if (madera_fllao_settings[i].fin == fin && + madera_fllao_settings[i].fout == fout) + break; + } + + if (i == ARRAY_SIZE(madera_fllao_settings)) { + madera_fll_err(fll, + "No matching configuration for FLL_AO\n"); + return -EINVAL; + } + + patch = madera_fllao_settings[i].patch; + patch_size = madera_fllao_settings[i].patch_size; + } + + fll->ref_src = source; + fll->ref_freq = fin; + fll->fout = fout; + + if (fout) + ret = madera_enable_fll_ao(fll, patch, patch_size); + else + madera_disable_fll_ao(fll); + + return ret; +} +EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk); + +/** + * madera_set_output_mode - Set the mode of the specified output + * + * @component: Device to configure + * @output: Output number + * @diff: True to set the output to differential mode + * + * Some systems use external analogue switches to connect more + * analogue devices to the CODEC than are supported by the device. In + * some systems this requires changing the switched output from single + * ended to differential mode dynamically at runtime, an operation + * supported using this function. + * + * Most systems have a single static configuration and should use + * platform data instead. + */ +int madera_set_output_mode(struct snd_soc_component *component, int output, + bool differential) +{ + unsigned int reg, val; + int ret; + + if (output < 1 || output > MADERA_MAX_OUTPUT) + return -EINVAL; + + reg = MADERA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8; + + if (differential) + val = MADERA_OUT1_MONO; + else + val = 0; + + ret = snd_soc_component_update_bits(component, reg, MADERA_OUT1_MONO, + val); + if (ret < 0) + return ret; + else + return 0; +} +EXPORT_SYMBOL_GPL(madera_set_output_mode); + +static bool madera_eq_filter_unstable(bool mode, __be16 _a, __be16 _b) +{ + s16 a = be16_to_cpu(_a); + s16 b = be16_to_cpu(_b); + + if (!mode) { + return abs(a) >= 4096; + } else { + if (abs(b) >= 4096) + return true; + + return (abs((a << 16) / (4096 - b)) >= 4096 << 4); + } +} + +int madera_eq_coeff_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + struct soc_bytes *params = (void *)kcontrol->private_value; + unsigned int val; + __be16 *data; + int len; + int ret; + + len = params->num_regs * regmap_get_val_bytes(madera->regmap); + + data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); + if (!data) + return -ENOMEM; + + data[0] &= cpu_to_be16(MADERA_EQ1_B1_MODE); + + if (madera_eq_filter_unstable(!!data[0], data[1], data[2]) || + madera_eq_filter_unstable(true, data[4], data[5]) || + madera_eq_filter_unstable(true, data[8], data[9]) || + madera_eq_filter_unstable(true, data[12], data[13]) || + madera_eq_filter_unstable(false, data[16], data[17])) { + dev_err(madera->dev, "Rejecting unstable EQ coefficients\n"); + ret = -EINVAL; + goto out; + } + + ret = regmap_read(madera->regmap, params->base, &val); + if (ret != 0) + goto out; + + val &= ~MADERA_EQ1_B1_MODE; + data[0] |= cpu_to_be16(val); + + ret = regmap_raw_write(madera->regmap, params->base, data, len); + +out: + kfree(data); + + return ret; +} +EXPORT_SYMBOL_GPL(madera_eq_coeff_put); + +int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + __be16 *data = (__be16 *)ucontrol->value.bytes.data; + s16 val = be16_to_cpu(*data); + + if (abs(val) >= 4096) { + dev_err(madera->dev, "Rejecting unstable LHPF coefficients\n"); + return -EINVAL; + } + + return snd_soc_bytes_put(kcontrol, ucontrol); +} +EXPORT_SYMBOL_GPL(madera_lhpf_coeff_put); + +MODULE_SOFTDEP("pre: madera"); +MODULE_DESCRIPTION("ASoC Cirrus Logic Madera codec support"); +MODULE_AUTHOR("Charles Keepax "); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/madera.h b/sound/soc/codecs/madera.h new file mode 100644 index 000000000000..aa2db156582b --- /dev/null +++ b/sound/soc/codecs/madera.h @@ -0,0 +1,446 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Cirrus Logic Madera class codecs common support + * + * Copyright (C) 2015-2018 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2. + */ + +#ifndef ASOC_MADERA_H +#define ASOC_MADERA_H + +#include +#include +#include + +#include "wm_adsp.h" + +#define MADERA_FLL1_REFCLK 1 +#define MADERA_FLL2_REFCLK 2 +#define MADERA_FLL3_REFCLK 3 +#define MADERA_FLLAO_REFCLK 4 +#define MADERA_FLL1_SYNCCLK 5 +#define MADERA_FLL2_SYNCCLK 6 +#define MADERA_FLL3_SYNCCLK 7 +#define MADERA_FLLAO_SYNCCLK 8 + +#define MADERA_FLL_SRC_NONE -1 +#define MADERA_FLL_SRC_MCLK1 0 +#define MADERA_FLL_SRC_MCLK2 1 +#define MADERA_FLL_SRC_SLIMCLK 3 +#define MADERA_FLL_SRC_FLL1 4 +#define MADERA_FLL_SRC_FLL2 5 +#define MADERA_FLL_SRC_AIF1BCLK 8 +#define MADERA_FLL_SRC_AIF2BCLK 9 +#define MADERA_FLL_SRC_AIF3BCLK 10 +#define MADERA_FLL_SRC_AIF4BCLK 11 +#define MADERA_FLL_SRC_AIF1LRCLK 12 +#define MADERA_FLL_SRC_AIF2LRCLK 13 +#define MADERA_FLL_SRC_AIF3LRCLK 14 +#define MADERA_FLL_SRC_AIF4LRCLK 15 + +#define MADERA_CLK_SYSCLK_1 1 +#define MADERA_CLK_ASYNCCLK_1 2 +#define MADERA_CLK_OPCLK 3 +#define MADERA_CLK_ASYNC_OPCLK 4 +#define MADERA_CLK_SYSCLK_2 5 +#define MADERA_CLK_SYSCLK_3 6 +#define MADERA_CLK_ASYNCCLK_2 7 +#define MADERA_CLK_DSPCLK 8 + +#define MADERA_CLK_SRC_MCLK1 0x0 +#define MADERA_CLK_SRC_MCLK2 0x1 +#define MADERA_CLK_SRC_FLL1 0x4 +#define MADERA_CLK_SRC_FLL2 0x5 +#define MADERA_CLK_SRC_FLL3 0x6 +#define MADERA_CLK_SRC_FLLAO_HI 0x7 +#define MADERA_CLK_SRC_FLL1_DIV6 0x7 +#define MADERA_CLK_SRC_AIF1BCLK 0x8 +#define MADERA_CLK_SRC_AIF2BCLK 0x9 +#define MADERA_CLK_SRC_AIF3BCLK 0xA +#define MADERA_CLK_SRC_AIF4BCLK 0xB +#define MADERA_CLK_SRC_FLLAO 0xF + +#define MADERA_MIXER_VOL_MASK 0x00FE +#define MADERA_MIXER_VOL_SHIFT 1 +#define MADERA_MIXER_VOL_WIDTH 7 + +#define MADERA_DOM_GRP_FX 0 +#define MADERA_DOM_GRP_ASRC1 1 +#define MADERA_DOM_GRP_ASRC2 2 +#define MADERA_DOM_GRP_ISRC1 3 +#define MADERA_DOM_GRP_ISRC2 4 +#define MADERA_DOM_GRP_ISRC3 5 +#define MADERA_DOM_GRP_ISRC4 6 +#define MADERA_DOM_GRP_OUT 7 +#define MADERA_DOM_GRP_SPD 8 +#define MADERA_DOM_GRP_DSP1 9 +#define MADERA_DOM_GRP_DSP2 10 +#define MADERA_DOM_GRP_DSP3 11 +#define MADERA_DOM_GRP_DSP4 12 +#define MADERA_DOM_GRP_DSP5 13 +#define MADERA_DOM_GRP_DSP6 14 +#define MADERA_DOM_GRP_DSP7 15 +#define MADERA_DOM_GRP_AIF1 16 +#define MADERA_DOM_GRP_AIF2 17 +#define MADERA_DOM_GRP_AIF3 18 +#define MADERA_DOM_GRP_AIF4 19 +#define MADERA_DOM_GRP_SLIMBUS 20 +#define MADERA_DOM_GRP_PWM 21 +#define MADERA_DOM_GRP_DFC 22 +#define MADERA_N_DOM_GRPS 23 + +#define MADERA_MAX_DAI 11 +#define MADERA_MAX_ADSP 7 + +#define MADERA_NUM_MIXER_INPUTS 148 + +struct madera; +struct wm_adsp; + +struct madera_voice_trigger_info { + /** Which core triggered, 1-based (1 = DSP1, ...) */ + int core_num; +}; + +struct madera_dai_priv { + int clk; + struct snd_pcm_hw_constraint_list constraint; +}; + +struct madera_priv { + struct wm_adsp adsp[MADERA_MAX_ADSP]; + struct madera *madera; + struct device *dev; + int sysclk; + int asyncclk; + int dspclk; + struct madera_dai_priv dai[MADERA_MAX_DAI]; + + int num_inputs; + + unsigned int in_pending; + + unsigned int out_up_pending; + unsigned int out_up_delay; + unsigned int out_down_pending; + unsigned int out_down_delay; + + unsigned int adsp_rate_cache[MADERA_MAX_ADSP]; + + struct mutex rate_lock; + + int tdm_width[MADERA_MAX_AIF]; + int tdm_slots[MADERA_MAX_AIF]; + + int domain_group_ref[MADERA_N_DOM_GRPS]; +}; + +struct madera_fll_cfg { + int n; + unsigned int theta; + unsigned int lambda; + int refdiv; + int fratio; + int gain; + int alt_gain; +}; + +struct madera_fll { + struct madera *madera; + int id; + unsigned int base; + + unsigned int fout; + + int sync_src; + unsigned int sync_freq; + + int ref_src; + unsigned int ref_freq; + struct madera_fll_cfg ref_cfg; +}; + +struct madera_enum { + struct soc_enum mixer_enum; + int val; +}; + +extern const unsigned int madera_ana_tlv[]; +extern const unsigned int madera_eq_tlv[]; +extern const unsigned int madera_digital_tlv[]; +extern const unsigned int madera_noise_tlv[]; +extern const unsigned int madera_ng_tlv[]; + +extern const unsigned int madera_mixer_tlv[]; +extern const char * const madera_mixer_texts[MADERA_NUM_MIXER_INPUTS]; +extern const unsigned int madera_mixer_values[MADERA_NUM_MIXER_INPUTS]; + +#define MADERA_GAINMUX_CONTROLS(name, base) \ + SOC_SINGLE_RANGE_TLV(name " Input Volume", base + 1, \ + MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ + madera_mixer_tlv) + +#define MADERA_MIXER_CONTROLS(name, base) \ + SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base + 1, \ + MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ + madera_mixer_tlv), \ + SOC_SINGLE_RANGE_TLV(name " Input 2 Volume", base + 3, \ + MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ + madera_mixer_tlv), \ + SOC_SINGLE_RANGE_TLV(name " Input 3 Volume", base + 5, \ + MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ + madera_mixer_tlv), \ + SOC_SINGLE_RANGE_TLV(name " Input 4 Volume", base + 7, \ + MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ + madera_mixer_tlv) + +#define MADERA_MUX_ENUM_DECL(name, reg) \ + SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL( \ + name, reg, 0, 0xff, madera_mixer_texts, madera_mixer_values) + +#define MADERA_MUX_CTL_DECL(name) \ + const struct snd_kcontrol_new name##_mux = \ + SOC_DAPM_ENUM("Route", name##_enum) + +#define MADERA_MUX_ENUMS(name, base_reg) \ + static MADERA_MUX_ENUM_DECL(name##_enum, base_reg); \ + static MADERA_MUX_CTL_DECL(name) + +#define MADERA_MIXER_ENUMS(name, base_reg) \ + MADERA_MUX_ENUMS(name##_in1, base_reg); \ + MADERA_MUX_ENUMS(name##_in2, base_reg + 2); \ + MADERA_MUX_ENUMS(name##_in3, base_reg + 4); \ + MADERA_MUX_ENUMS(name##_in4, base_reg + 6) + +#define MADERA_DSP_AUX_ENUMS(name, base_reg) \ + MADERA_MUX_ENUMS(name##_aux1, base_reg); \ + MADERA_MUX_ENUMS(name##_aux2, base_reg + 8); \ + MADERA_MUX_ENUMS(name##_aux3, base_reg + 16); \ + MADERA_MUX_ENUMS(name##_aux4, base_reg + 24); \ + MADERA_MUX_ENUMS(name##_aux5, base_reg + 32); \ + MADERA_MUX_ENUMS(name##_aux6, base_reg + 40) + +#define MADERA_MUX(name, ctrl) \ + SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) + +#define MADERA_MUX_WIDGETS(name, name_str) \ + MADERA_MUX(name_str " Input 1", &name##_mux) + +#define MADERA_MIXER_WIDGETS(name, name_str) \ + MADERA_MUX(name_str " Input 1", &name##_in1_mux), \ + MADERA_MUX(name_str " Input 2", &name##_in2_mux), \ + MADERA_MUX(name_str " Input 3", &name##_in3_mux), \ + MADERA_MUX(name_str " Input 4", &name##_in4_mux), \ + SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) + +#define MADERA_DSP_WIDGETS(name, name_str) \ + MADERA_MIXER_WIDGETS(name##L, name_str "L"), \ + MADERA_MIXER_WIDGETS(name##R, name_str "R"), \ + MADERA_MUX(name_str " Aux 1", &name##_aux1_mux), \ + MADERA_MUX(name_str " Aux 2", &name##_aux2_mux), \ + MADERA_MUX(name_str " Aux 3", &name##_aux3_mux), \ + MADERA_MUX(name_str " Aux 4", &name##_aux4_mux), \ + MADERA_MUX(name_str " Aux 5", &name##_aux5_mux), \ + MADERA_MUX(name_str " Aux 6", &name##_aux6_mux) + +#define MADERA_MUX_ROUTES(widget, name) \ + { widget, NULL, name " Input 1" }, \ + MADERA_MIXER_INPUT_ROUTES(name " Input 1") + +#define MADERA_MIXER_ROUTES(widget, name) \ + { widget, NULL, name " Mixer" }, \ + { name " Mixer", NULL, name " Input 1" }, \ + { name " Mixer", NULL, name " Input 2" }, \ + { name " Mixer", NULL, name " Input 3" }, \ + { name " Mixer", NULL, name " Input 4" }, \ + MADERA_MIXER_INPUT_ROUTES(name " Input 1"), \ + MADERA_MIXER_INPUT_ROUTES(name " Input 2"), \ + MADERA_MIXER_INPUT_ROUTES(name " Input 3"), \ + MADERA_MIXER_INPUT_ROUTES(name " Input 4") + +#define MADERA_DSP_ROUTES(name) \ + { name, NULL, name " Preloader"}, \ + { name " Preload", NULL, name " Preloader"}, \ + { name, NULL, "SYSCLK"}, \ + { name, NULL, "DSPCLK"}, \ + { name, NULL, name " Aux 1" }, \ + { name, NULL, name " Aux 2" }, \ + { name, NULL, name " Aux 3" }, \ + { name, NULL, name " Aux 4" }, \ + { name, NULL, name " Aux 5" }, \ + { name, NULL, name " Aux 6" }, \ + MADERA_MIXER_INPUT_ROUTES(name " Aux 1"), \ + MADERA_MIXER_INPUT_ROUTES(name " Aux 2"), \ + MADERA_MIXER_INPUT_ROUTES(name " Aux 3"), \ + MADERA_MIXER_INPUT_ROUTES(name " Aux 4"), \ + MADERA_MIXER_INPUT_ROUTES(name " Aux 5"), \ + MADERA_MIXER_INPUT_ROUTES(name " Aux 6"), \ + MADERA_MIXER_ROUTES(name, name "L"), \ + MADERA_MIXER_ROUTES(name, name "R") + +#define MADERA_RATE_ENUM(xname, xenum) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ + .info = snd_soc_info_enum_double, \ + .get = snd_soc_get_enum_double, .put = madera_rate_put, \ + .private_value = (unsigned long)&xenum } + +#define MADERA_EQ_CONTROL(xname, xbase) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \ + .put = madera_eq_coeff_put, .private_value = \ + ((unsigned long)&(struct soc_bytes) { .base = xbase, \ + .num_regs = 20, .mask = ~MADERA_EQ1_B1_MODE }) } + +#define MADERA_LHPF_CONTROL(xname, xbase) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \ + .put = madera_lhpf_coeff_put, .private_value = \ + ((unsigned long)&(struct soc_bytes) { .base = xbase, \ + .num_regs = 1 }) } + +#define MADERA_RATES SNDRV_PCM_RATE_KNOT + +#define MADERA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +#define MADERA_OSR_ENUM_SIZE 5 +#define MADERA_SYNC_RATE_ENUM_SIZE 3 +#define MADERA_ASYNC_RATE_ENUM_SIZE 2 +#define MADERA_RATE_ENUM_SIZE \ + (MADERA_SYNC_RATE_ENUM_SIZE + MADERA_ASYNC_RATE_ENUM_SIZE) +#define MADERA_SAMPLE_RATE_ENUM_SIZE 16 +#define MADERA_DFC_TYPE_ENUM_SIZE 5 +#define MADERA_DFC_WIDTH_ENUM_SIZE 5 + +extern const struct snd_soc_dai_ops madera_dai_ops; +extern const struct snd_soc_dai_ops madera_simple_dai_ops; + +extern const struct snd_kcontrol_new madera_inmux[]; +extern const struct snd_kcontrol_new madera_inmode[]; + +extern const char * const madera_rate_text[MADERA_RATE_ENUM_SIZE]; +extern const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE]; + +extern const struct soc_enum madera_sample_rate[]; +extern const struct soc_enum madera_isrc_fsl[]; +extern const struct soc_enum madera_isrc_fsh[]; +extern const struct soc_enum madera_asrc1_rate[]; +extern const struct soc_enum madera_asrc2_rate[]; +extern const struct soc_enum madera_dfc_width[]; +extern const struct soc_enum madera_dfc_type[]; + +extern const struct soc_enum madera_in_vi_ramp; +extern const struct soc_enum madera_in_vd_ramp; + +extern const struct soc_enum madera_out_vi_ramp; +extern const struct soc_enum madera_out_vd_ramp; + +extern const struct soc_enum madera_lhpf1_mode; +extern const struct soc_enum madera_lhpf2_mode; +extern const struct soc_enum madera_lhpf3_mode; +extern const struct soc_enum madera_lhpf4_mode; + +extern const struct soc_enum madera_ng_hold; +extern const struct soc_enum madera_in_hpf_cut_enum; +extern const struct soc_enum madera_in_dmic_osr[]; + +extern const struct soc_enum madera_output_anc_src[]; +extern const struct soc_enum madera_anc_input_src[]; +extern const struct soc_enum madera_anc_ng_enum; + +extern const struct snd_kcontrol_new madera_dsp_trigger_output_mux[]; +extern const struct snd_kcontrol_new madera_drc_activity_output_mux[]; + +extern const struct snd_kcontrol_new madera_adsp_rate_controls[]; + +int madera_dfc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + +int madera_lp_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + +int madera_out1_demux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int madera_out1_demux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + +int madera_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + +int madera_eq_coeff_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + +int madera_sysclk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +int madera_spk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +int madera_in_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +int madera_out_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +int madera_hp_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +int madera_anc_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +int madera_domain_clk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event); + +int madera_set_adsp_clk(struct madera_priv *priv, int dsp_num, + unsigned int freq); + +int madera_set_sysclk(struct snd_soc_component *component, int clk_id, + int source, unsigned int freq, int dir); + +int madera_init_fll(struct madera *madera, int id, int base, + struct madera_fll *fll); +int madera_set_fll_refclk(struct madera_fll *fll, int source, + unsigned int fref, unsigned int fout); +int madera_set_fll_syncclk(struct madera_fll *fll, int source, + unsigned int fref, unsigned int fout); +int madera_set_fll_ao_refclk(struct madera_fll *fll, int source, + unsigned int fin, unsigned int fout); + +int madera_core_init(struct madera_priv *priv); +int madera_core_free(struct madera_priv *priv); +int madera_init_overheat(struct madera_priv *priv); +int madera_free_overheat(struct madera_priv *priv); +int madera_init_inputs(struct snd_soc_component *component); +int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes); +int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num, + irq_handler_t handler); +void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num); + +int madera_init_dai(struct madera_priv *priv, int dai); + +int madera_set_output_mode(struct snd_soc_component *component, int output, + bool differential); + +/* Following functions are for use by machine drivers */ +static inline int madera_register_notifier(struct snd_soc_component *component, + struct notifier_block *nb) +{ + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + + return blocking_notifier_chain_register(&madera->notifier, nb); +} + +static inline int +madera_unregister_notifier(struct snd_soc_component *component, + struct notifier_block *nb) +{ + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + + return blocking_notifier_chain_unregister(&madera->notifier, nb); +} + +#endif From e6a2b5c0b7ebd28bc44117cf27b5308a288c7925 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 19 Jun 2019 14:41:57 +0100 Subject: [PATCH 477/626] ASoC: cs47l35: Add codec driver for Cirrus Logic CS47L35 Adds the codec driver for the CS47L35 SmartCodec. This is a multi-functional codec based on the Cirrus Logic Madera platform. Signed-off-by: Piotr Stankiewicz Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/cs47l35.c | 1782 ++++++++++++++++++++++++++++++++++++ 3 files changed, 1790 insertions(+) create mode 100644 sound/soc/codecs/cs47l35.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f3ac661b8845..5b3f7775510c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -70,6 +70,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI select SND_SOC_CS4349 if I2C select SND_SOC_CS47L24 if MFD_CS47L24 + select SND_SOC_CS47L35 if MFD_CS47L35 select SND_SOC_CS53L30 if I2C select SND_SOC_CX20442 if TTY select SND_SOC_CX2072X if I2C @@ -579,6 +580,9 @@ config SND_SOC_CS4349 config SND_SOC_CS47L24 tristate +config SND_SOC_CS47L35 + tristate + # Cirrus Logic Quad-Channel ADC config SND_SOC_CS53L30 tristate "Cirrus Logic CS53L30 CODEC" @@ -708,6 +712,8 @@ config SND_SOC_LOCHNAGAR_SC config SND_SOC_MADERA tristate + default y if SND_SOC_CS47L35=y + default m if SND_SOC_CS47L35=m config SND_SOC_MAX98088 tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d21e1be3e7a7..55239f0bfad0 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -65,6 +65,7 @@ snd-soc-cs43130-objs := cs43130.o snd-soc-cs4341-objs := cs4341.o snd-soc-cs4349-objs := cs4349.o snd-soc-cs47l24-objs := cs47l24.o +snd-soc-cs47l35-objs := cs47l35.o snd-soc-cs53l30-objs := cs53l30.o snd-soc-cx20442-objs := cx20442.o snd-soc-cx2072x-objs := cx2072x.o @@ -342,6 +343,7 @@ obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o +obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c new file mode 100644 index 000000000000..02f193dadd41 --- /dev/null +++ b/sound/soc/codecs/cs47l35.c @@ -0,0 +1,1782 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// ALSA SoC Audio driver for CS47L35 codec +// +// Copyright (C) 2015-2019 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by the +// Free Software Foundation; version 2. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "madera.h" +#include "wm_adsp.h" + +#define CS47L35_NUM_ADSP 3 +#define CS47L35_MONO_OUTPUTS 1 + +#define DRV_NAME "cs47l35-codec" + +struct cs47l35 { + struct madera_priv core; + struct madera_fll fll; +}; + +static const struct wm_adsp_region cs47l35_dsp1_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x080000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x0e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x0a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x0c0000 }, +}; + +static const struct wm_adsp_region cs47l35_dsp2_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x100000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x160000 }, + { .type = WMFW_ADSP2_XM, .base = 0x120000 }, + { .type = WMFW_ADSP2_YM, .base = 0x140000 }, +}; + +static const struct wm_adsp_region cs47l35_dsp3_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x180000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x1e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x1a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x1c0000 }, +}; + +static const struct wm_adsp_region *cs47l35_dsp_regions[] = { + cs47l35_dsp1_regions, + cs47l35_dsp2_regions, + cs47l35_dsp3_regions, +}; + +static const int wm_adsp2_control_bases[] = { + MADERA_DSP1_CONFIG_1, + MADERA_DSP2_CONFIG_1, + MADERA_DSP3_CONFIG_1, +}; + +static const char * const cs47l35_outdemux_texts[] = { + "HPOUT", + "EPOUT", +}; + +static SOC_ENUM_SINGLE_DECL(cs47l35_outdemux_enum, SND_SOC_NOPM, 0, + cs47l35_outdemux_texts); + +static const struct snd_kcontrol_new cs47l35_outdemux = + SOC_DAPM_ENUM_EXT("HPOUT1 Demux", cs47l35_outdemux_enum, + madera_out1_demux_get, madera_out1_demux_put); + +static int cs47l35_adsp_power_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct cs47l35 *cs47l35 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l35->core; + struct madera *madera = priv->madera; + unsigned int freq; + int ret; + + ret = regmap_read(madera->regmap, MADERA_DSP_CLOCK_1, &freq); + if (ret != 0) { + dev_err(madera->dev, + "Failed to read MADERA_DSP_CLOCK_1: %d\n", ret); + return ret; + } + + freq &= MADERA_DSP_CLK_FREQ_LEGACY_MASK; + freq >>= MADERA_DSP_CLK_FREQ_LEGACY_SHIFT; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = madera_set_adsp_clk(&cs47l35->core, w->shift, freq); + if (ret) + return ret; + break; + default: + break; + } + + return wm_adsp_early_event(w, kcontrol, event); +} + +#define CS47L35_NG_SRC(name, base) \ + SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ + SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ + SOC_SINGLE(name " NG SPKOUT Switch", base, 6, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0) + +static void cs47l35_hp_post_enable(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + unsigned int val; + int ret; + + switch (w->shift) { + case MADERA_OUT1L_ENA_SHIFT: + case MADERA_OUT1R_ENA_SHIFT: + ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, + &val); + if (ret) { + dev_err(component->dev, + "Failed to check output enables: %d\n", ret); + return; + } + + val &= (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA); + + if (val != (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA)) + break; + + snd_soc_component_update_bits(component, + MADERA_EDRE_HP_STEREO_CONTROL, + 0x0001, 1); + break; + default: + break; + } +} + +static void cs47l35_hp_post_disable(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + switch (w->shift) { + case MADERA_OUT1L_ENA_SHIFT: + snd_soc_component_write(component, MADERA_DCS_HP1L_CONTROL, + 0x2006); + break; + case MADERA_OUT1R_ENA_SHIFT: + snd_soc_component_write(component, MADERA_DCS_HP1R_CONTROL, + 0x2006); + break; + default: + return; + } + + /* Only get to here for OUT1L and OUT1R */ + snd_soc_component_update_bits(component, + MADERA_EDRE_HP_STEREO_CONTROL, + 0x0001, 0); +} + +static int cs47l35_hp_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + case SND_SOC_DAPM_PRE_PMD: + return madera_hp_ev(w, kcontrol, event); + case SND_SOC_DAPM_POST_PMU: + ret = madera_hp_ev(w, kcontrol, event); + if (ret < 0) + return ret; + + cs47l35_hp_post_enable(w); + return 0; + case SND_SOC_DAPM_POST_PMD: + ret = madera_hp_ev(w, kcontrol, event); + cs47l35_hp_post_disable(w); + return ret; + default: + return -EINVAL; + } +} + +static const struct snd_kcontrol_new cs47l35_snd_controls[] = { +SOC_ENUM("IN1 OSR", madera_in_dmic_osr[0]), +SOC_ENUM("IN2 OSR", madera_in_dmic_osr[1]), + +SOC_SINGLE_RANGE_TLV("IN1L Volume", MADERA_IN1L_CONTROL, + MADERA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN1R Volume", MADERA_IN1R_CONTROL, + MADERA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2L Volume", MADERA_IN2L_CONTROL, + MADERA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2R Volume", MADERA_IN2R_CONTROL, + MADERA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), + +SOC_ENUM("IN HPF Cutoff Frequency", madera_in_hpf_cut_enum), + +SOC_SINGLE("IN1L HPF Switch", MADERA_IN1L_CONTROL, + MADERA_IN1L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN1R HPF Switch", MADERA_IN1R_CONTROL, + MADERA_IN1R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2L HPF Switch", MADERA_IN2L_CONTROL, + MADERA_IN2L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2R HPF Switch", MADERA_IN2R_CONTROL, + MADERA_IN2R_HPF_SHIFT, 1, 0), + +SOC_SINGLE_TLV("IN1L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1L, + MADERA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN1R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1R, + MADERA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2L, + MADERA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2R, + MADERA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), + +SOC_ENUM("Input Ramp Up", madera_in_vi_ramp), +SOC_ENUM("Input Ramp Down", madera_in_vd_ramp), + +MADERA_MIXER_CONTROLS("EQ1", MADERA_EQ1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ2", MADERA_EQ2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ3", MADERA_EQ3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ4", MADERA_EQ4MIX_INPUT_1_SOURCE), + +MADERA_EQ_CONTROL("EQ1 Coefficients", MADERA_EQ1_2), +SOC_SINGLE_TLV("EQ1 B1 Volume", MADERA_EQ1_1, MADERA_EQ1_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B2 Volume", MADERA_EQ1_1, MADERA_EQ1_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B3 Volume", MADERA_EQ1_1, MADERA_EQ1_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B4 Volume", MADERA_EQ1_2, MADERA_EQ1_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B5 Volume", MADERA_EQ1_2, MADERA_EQ1_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ2 Coefficients", MADERA_EQ2_2), +SOC_SINGLE_TLV("EQ2 B1 Volume", MADERA_EQ2_1, MADERA_EQ2_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B2 Volume", MADERA_EQ2_1, MADERA_EQ2_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B3 Volume", MADERA_EQ2_1, MADERA_EQ2_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B4 Volume", MADERA_EQ2_2, MADERA_EQ2_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B5 Volume", MADERA_EQ2_2, MADERA_EQ2_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ3 Coefficients", MADERA_EQ3_2), +SOC_SINGLE_TLV("EQ3 B1 Volume", MADERA_EQ3_1, MADERA_EQ3_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B2 Volume", MADERA_EQ3_1, MADERA_EQ3_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B3 Volume", MADERA_EQ3_1, MADERA_EQ3_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B4 Volume", MADERA_EQ3_2, MADERA_EQ3_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B5 Volume", MADERA_EQ3_2, MADERA_EQ3_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ4 Coefficients", MADERA_EQ4_2), +SOC_SINGLE_TLV("EQ4 B1 Volume", MADERA_EQ4_1, MADERA_EQ4_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B2 Volume", MADERA_EQ4_1, MADERA_EQ4_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B3 Volume", MADERA_EQ4_1, MADERA_EQ4_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B4 Volume", MADERA_EQ4_2, MADERA_EQ4_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B5 Volume", MADERA_EQ4_2, MADERA_EQ4_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_MIXER_CONTROLS("DRC1L", MADERA_DRC1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC1R", MADERA_DRC1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2L", MADERA_DRC2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2R", MADERA_DRC2RMIX_INPUT_1_SOURCE), + +SND_SOC_BYTES_MASK("DRC1", MADERA_DRC1_CTRL1, 5, + MADERA_DRC1R_ENA | MADERA_DRC1L_ENA), +SND_SOC_BYTES_MASK("DRC2", MADERA_DRC2_CTRL1, 5, + MADERA_DRC2R_ENA | MADERA_DRC2L_ENA), + +MADERA_MIXER_CONTROLS("LHPF1", MADERA_HPLP1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF2", MADERA_HPLP2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF3", MADERA_HPLP3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF4", MADERA_HPLP4MIX_INPUT_1_SOURCE), + +MADERA_LHPF_CONTROL("LHPF1 Coefficients", MADERA_HPLPF1_2), +MADERA_LHPF_CONTROL("LHPF2 Coefficients", MADERA_HPLPF2_2), +MADERA_LHPF_CONTROL("LHPF3 Coefficients", MADERA_HPLPF3_2), +MADERA_LHPF_CONTROL("LHPF4 Coefficients", MADERA_HPLPF4_2), + +SOC_ENUM("LHPF1 Mode", madera_lhpf1_mode), +SOC_ENUM("LHPF2 Mode", madera_lhpf2_mode), +SOC_ENUM("LHPF3 Mode", madera_lhpf3_mode), +SOC_ENUM("LHPF4 Mode", madera_lhpf4_mode), + +MADERA_RATE_ENUM("ISRC1 FSL", madera_isrc_fsl[0]), +MADERA_RATE_ENUM("ISRC2 FSL", madera_isrc_fsl[1]), +MADERA_RATE_ENUM("ISRC1 FSH", madera_isrc_fsh[0]), +MADERA_RATE_ENUM("ISRC2 FSH", madera_isrc_fsh[1]), + +WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), +WM_ADSP2_PRELOAD_SWITCH("DSP2", 2), +WM_ADSP2_PRELOAD_SWITCH("DSP3", 3), + +MADERA_MIXER_CONTROLS("DSP1L", MADERA_DSP1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP1R", MADERA_DSP1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP2L", MADERA_DSP2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP2R", MADERA_DSP2RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP3L", MADERA_DSP3LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP3R", MADERA_DSP3RMIX_INPUT_1_SOURCE), + +SOC_SINGLE_TLV("Noise Generator Volume", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, madera_noise_tlv), + +MADERA_MIXER_CONTROLS("HPOUT1L", MADERA_OUT1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT1R", MADERA_OUT1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKOUT", MADERA_OUT4LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1L", MADERA_OUT5LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1R", MADERA_OUT5RMIX_INPUT_1_SOURCE), + +SOC_SINGLE("HPOUT1 SC Protect Switch", MADERA_HP1_SHORT_CIRCUIT_CTRL, + MADERA_HP1_SC_ENA_SHIFT, 1, 0), + +SOC_SINGLE("SPKDAT1 High Performance Switch", MADERA_OUTPUT_PATH_CONFIG_5L, + MADERA_OUT5_OSR_SHIFT, 1, 0), + +SOC_DOUBLE_R("HPOUT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_MUTE_SHIFT, 1, 1), +SOC_SINGLE("Speaker Digital Switch", MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_OUT4L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_MUTE_SHIFT, 1, 1), + +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("Speaker Digital Volume", MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_OUT4L_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), + +SOC_DOUBLE("SPKDAT1 Switch", MADERA_PDM_SPK1_CTRL_1, MADERA_SPK1L_MUTE_SHIFT, + MADERA_SPK1R_MUTE_SHIFT, 1, 1), + +SOC_ENUM("Output Ramp Up", madera_out_vi_ramp), +SOC_ENUM("Output Ramp Down", madera_out_vd_ramp), + +SOC_SINGLE("Noise Gate Switch", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_ENA_SHIFT, 1, 0), +SOC_SINGLE_TLV("Noise Gate Threshold Volume", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_THR_SHIFT, 7, 1, madera_ng_tlv), +SOC_ENUM("Noise Gate Hold", madera_ng_hold), + +CS47L35_NG_SRC("HPOUT1L", MADERA_NOISE_GATE_SELECT_1L), +CS47L35_NG_SRC("HPOUT1R", MADERA_NOISE_GATE_SELECT_1R), +CS47L35_NG_SRC("SPKOUT", MADERA_NOISE_GATE_SELECT_4L), +CS47L35_NG_SRC("SPKDAT1L", MADERA_NOISE_GATE_SELECT_5L), +CS47L35_NG_SRC("SPKDAT1R", MADERA_NOISE_GATE_SELECT_5R), + +MADERA_MIXER_CONTROLS("AIF1TX1", MADERA_AIF1TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX2", MADERA_AIF1TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX3", MADERA_AIF1TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX4", MADERA_AIF1TX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX5", MADERA_AIF1TX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX6", MADERA_AIF1TX6MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF2TX1", MADERA_AIF2TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX2", MADERA_AIF2TX2MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF3TX1", MADERA_AIF3TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF3TX2", MADERA_AIF3TX2MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("SLIMTX1", MADERA_SLIMTX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX2", MADERA_SLIMTX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX3", MADERA_SLIMTX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX4", MADERA_SLIMTX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX5", MADERA_SLIMTX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX6", MADERA_SLIMTX6MIX_INPUT_1_SOURCE), + +MADERA_GAINMUX_CONTROLS("SPDIF1TX1", MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE), +MADERA_GAINMUX_CONTROLS("SPDIF1TX2", MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP1", 0), +WM_ADSP_FW_CONTROL("DSP2", 1), +WM_ADSP_FW_CONTROL("DSP3", 2), +}; + +MADERA_MIXER_ENUMS(EQ1, MADERA_EQ1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ2, MADERA_EQ2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ3, MADERA_EQ3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ4, MADERA_EQ4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DRC1L, MADERA_DRC1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC1R, MADERA_DRC1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2L, MADERA_DRC2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2R, MADERA_DRC2RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(LHPF1, MADERA_HPLP1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF2, MADERA_HPLP2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF3, MADERA_HPLP3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF4, MADERA_HPLP4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP1L, MADERA_DSP1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP1R, MADERA_DSP1RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP1, MADERA_DSP1AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP2L, MADERA_DSP2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP2R, MADERA_DSP2RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP2, MADERA_DSP2AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP3L, MADERA_DSP3LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP3R, MADERA_DSP3RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP3, MADERA_DSP3AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(PWM1, MADERA_PWM1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(PWM2, MADERA_PWM2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(OUT1L, MADERA_OUT1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT1R, MADERA_OUT1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKOUT, MADERA_OUT4LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1L, MADERA_OUT5LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1R, MADERA_OUT5RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF1TX1, MADERA_AIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX2, MADERA_AIF1TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX3, MADERA_AIF1TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX4, MADERA_AIF1TX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX5, MADERA_AIF1TX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX6, MADERA_AIF1TX6MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF2TX1, MADERA_AIF2TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX2, MADERA_AIF2TX2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF3TX1, MADERA_AIF3TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF3TX2, MADERA_AIF3TX2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(SLIMTX1, MADERA_SLIMTX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX2, MADERA_SLIMTX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX3, MADERA_SLIMTX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX4, MADERA_SLIMTX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX5, MADERA_SLIMTX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX6, MADERA_SLIMTX6MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(SPD1TX1, MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(SPD1TX2, MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1INT1, MADERA_ISRC1INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT2, MADERA_ISRC1INT2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT3, MADERA_ISRC1INT3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT4, MADERA_ISRC1INT4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1DEC1, MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC2, MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC3, MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC4, MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2INT1, MADERA_ISRC2INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT2, MADERA_ISRC2INT2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT3, MADERA_ISRC2INT3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT4, MADERA_ISRC2INT4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2DEC1, MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC2, MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC3, MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC4, MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE); + +static const char * const cs47l35_aec_loopback_texts[] = { + "HPOUT1L", "HPOUT1R", "SPKOUT", "SPKDAT1L", "SPKDAT1R", +}; + +static const unsigned int cs47l35_aec_loopback_values[] = { + 0, 1, 6, 8, 9, +}; + +static const struct soc_enum cs47l35_aec1_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l35_aec_loopback_texts), + cs47l35_aec_loopback_texts, + cs47l35_aec_loopback_values); + +static const struct soc_enum cs47l35_aec2_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_2, + MADERA_AEC2_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l35_aec_loopback_texts), + cs47l35_aec_loopback_texts, + cs47l35_aec_loopback_values); + +static const struct snd_kcontrol_new cs47l35_aec_loopback_mux[] = { + SOC_DAPM_ENUM("AEC1 Loopback", cs47l35_aec1_loopback), + SOC_DAPM_ENUM("AEC2 Loopback", cs47l35_aec2_loopback), +}; + +static const struct snd_soc_dapm_widget cs47l35_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, + 0, madera_sysclk_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, + MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, 6, + 0, NULL, 0), + +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD2", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDD", 0, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS1", MADERA_MIC_BIAS_CTRL_1, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", MADERA_MIC_BIAS_CTRL_2, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS1A", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1A_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1B", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1B_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2A", MADERA_MIC_BIAS_CTRL_6, + MADERA_MICB2A_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2B", MADERA_MIC_BIAS_CTRL_6, + MADERA_MICB2B_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("FXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_FX, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_OUT, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SPD, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP3CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF1TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF2TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF3TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SLIMBUSCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SLIMBUS, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("PWMCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_PWM, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + +SND_SOC_DAPM_SIGGEN("TONE"), +SND_SOC_DAPM_SIGGEN("NOISE"), + +SND_SOC_DAPM_INPUT("IN1ALN"), +SND_SOC_DAPM_INPUT("IN1ALP"), +SND_SOC_DAPM_INPUT("IN1BLN"), +SND_SOC_DAPM_INPUT("IN1BLP"), +SND_SOC_DAPM_INPUT("IN1ARN"), +SND_SOC_DAPM_INPUT("IN1ARP"), +SND_SOC_DAPM_INPUT("IN1BRN"), +SND_SOC_DAPM_INPUT("IN1BRP"), +SND_SOC_DAPM_INPUT("IN2LN"), +SND_SOC_DAPM_INPUT("IN2LP"), +SND_SOC_DAPM_INPUT("IN2RN"), +SND_SOC_DAPM_INPUT("IN2RP"), + +SND_SOC_DAPM_MUX("IN1L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[0]), +SND_SOC_DAPM_MUX("IN1R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[1]), + +SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), +SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), + +SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), +SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), + +SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), +SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), + +SND_SOC_DAPM_OUTPUT("DSP Trigger Out"), + +SND_SOC_DAPM_DEMUX("HPOUT1 Demux", SND_SOC_NOPM, 0, 0, &cs47l35_outdemux), + +SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, + MADERA_OUT1L_ENA_SHIFT, 0, NULL, 0, cs47l35_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, + MADERA_OUT1R_ENA_SHIFT, 0, NULL, 0, cs47l35_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM, + MADERA_OUT4L_ENA_SHIFT, 0, NULL, 0, madera_spk_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA_E("OUT5L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("SPD1TX1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL1_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("SPD1TX2", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL2_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_OUT_DRV("SPD1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_ENA_SHIFT, 0, NULL, 0), + +/* + * Input mux widgets arranged in order of sources in MADERA_MIXER_INPUT_ROUTES + * to take advantage of cache lookup in DAPM + */ +SND_SOC_DAPM_PGA("Noise Generator", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Tone Generator 1", MADERA_TONE_GENERATOR_1, + MADERA_TONE1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("Tone Generator 2", MADERA_TONE_GENERATOR_1, + MADERA_TONE2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SIGGEN("HAPTICS"), + +SND_SOC_DAPM_MUX("AEC1 Loopback", MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_ENA_SHIFT, 0, + &cs47l35_aec_loopback_mux[0]), + +SND_SOC_DAPM_MUX("AEC2 Loopback", MADERA_DAC_AEC_CONTROL_2, + MADERA_AEC2_LOOPBACK_ENA_SHIFT, 0, + &cs47l35_aec_loopback_mux[1]), + +SND_SOC_DAPM_PGA_E("IN1L", MADERA_INPUT_ENABLES, MADERA_IN1L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN1R", MADERA_INPUT_ENABLES, MADERA_IN1R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA_E("IN2L", MADERA_INPUT_ENABLES, MADERA_IN2L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ2", MADERA_EQ2_1, MADERA_EQ2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ3", MADERA_EQ3_1, MADERA_EQ3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ4", MADERA_EQ4_1, MADERA_EQ4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("DRC1L", MADERA_DRC1_CTRL1, MADERA_DRC1L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC1R", MADERA_DRC1_CTRL1, MADERA_DRC1R_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2L", MADERA_DRC2_CTRL1, MADERA_DRC2L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2R", MADERA_DRC2_CTRL1, MADERA_DRC2R_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("LHPF1", MADERA_HPLPF1_1, MADERA_LHPF1_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF2", MADERA_HPLPF2_1, MADERA_LHPF2_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF3", MADERA_HPLPF3_1, MADERA_LHPF3_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF4", MADERA_HPLPF4_1, MADERA_LHPF4_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1DEC1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC3", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC4", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1INT1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT3", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT4", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2DEC1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC3", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC4", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2INT1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT3", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT4", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT4_ENA_SHIFT, 0, NULL, 0), + +WM_ADSP2("DSP1", 0, cs47l35_adsp_power_ev), +WM_ADSP2("DSP2", 1, cs47l35_adsp_power_ev), +WM_ADSP2("DSP3", 2, cs47l35_adsp_power_ev), + +/* End of ordered input mux widgets */ + +MADERA_MIXER_WIDGETS(EQ1, "EQ1"), +MADERA_MIXER_WIDGETS(EQ2, "EQ2"), +MADERA_MIXER_WIDGETS(EQ3, "EQ3"), +MADERA_MIXER_WIDGETS(EQ4, "EQ4"), + +MADERA_MIXER_WIDGETS(DRC1L, "DRC1L"), +MADERA_MIXER_WIDGETS(DRC1R, "DRC1R"), +MADERA_MIXER_WIDGETS(DRC2L, "DRC2L"), +MADERA_MIXER_WIDGETS(DRC2R, "DRC2R"), + +SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[0]), +SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[1]), + +MADERA_MIXER_WIDGETS(LHPF1, "LHPF1"), +MADERA_MIXER_WIDGETS(LHPF2, "LHPF2"), +MADERA_MIXER_WIDGETS(LHPF3, "LHPF3"), +MADERA_MIXER_WIDGETS(LHPF4, "LHPF4"), + +MADERA_MIXER_WIDGETS(PWM1, "PWM1"), +MADERA_MIXER_WIDGETS(PWM2, "PWM2"), + +MADERA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), +MADERA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), +MADERA_MIXER_WIDGETS(SPKOUT, "SPKOUT"), +MADERA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), +MADERA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), + +MADERA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), +MADERA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), +MADERA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), +MADERA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), +MADERA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), +MADERA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), + +MADERA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), +MADERA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), + +MADERA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), +MADERA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), + +MADERA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), +MADERA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), +MADERA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), +MADERA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), +MADERA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), +MADERA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), + +MADERA_MUX_WIDGETS(SPD1TX1, "SPDIF1TX1"), +MADERA_MUX_WIDGETS(SPD1TX2, "SPDIF1TX2"), + +MADERA_DSP_WIDGETS(DSP1, "DSP1"), +MADERA_DSP_WIDGETS(DSP2, "DSP2"), +MADERA_DSP_WIDGETS(DSP3, "DSP3"), + +SND_SOC_DAPM_SWITCH("DSP1 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[0]), +SND_SOC_DAPM_SWITCH("DSP2 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[1]), +SND_SOC_DAPM_SWITCH("DSP3 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[2]), + +MADERA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), +MADERA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), +MADERA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), +MADERA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), + +MADERA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), +MADERA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), +MADERA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), +MADERA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), + +MADERA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), +MADERA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), +MADERA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"), +MADERA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"), + +MADERA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), +MADERA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), +MADERA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"), +MADERA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"), + +SND_SOC_DAPM_OUTPUT("HPOUTL"), +SND_SOC_DAPM_OUTPUT("HPOUTR"), +SND_SOC_DAPM_OUTPUT("EPOUTP"), +SND_SOC_DAPM_OUTPUT("EPOUTN"), +SND_SOC_DAPM_OUTPUT("SPKOUTN"), +SND_SOC_DAPM_OUTPUT("SPKOUTP"), +SND_SOC_DAPM_OUTPUT("SPKDAT1L"), +SND_SOC_DAPM_OUTPUT("SPKDAT1R"), +SND_SOC_DAPM_OUTPUT("SPDIF1"), + +SND_SOC_DAPM_OUTPUT("MICSUPP"), +}; + +#define MADERA_MIXER_INPUT_ROUTES(name) \ + { name, "Noise Generator", "Noise Generator" }, \ + { name, "Tone Generator 1", "Tone Generator 1" }, \ + { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "Haptics", "HAPTICS" }, \ + { name, "AEC1", "AEC1 Loopback" }, \ + { name, "AEC2", "AEC2 Loopback" }, \ + { name, "IN1L", "IN1L" }, \ + { name, "IN1R", "IN1R" }, \ + { name, "IN2L", "IN2L" }, \ + { name, "IN2R", "IN2R" }, \ + { name, "AIF1RX1", "AIF1RX1" }, \ + { name, "AIF1RX2", "AIF1RX2" }, \ + { name, "AIF1RX3", "AIF1RX3" }, \ + { name, "AIF1RX4", "AIF1RX4" }, \ + { name, "AIF1RX5", "AIF1RX5" }, \ + { name, "AIF1RX6", "AIF1RX6" }, \ + { name, "AIF2RX1", "AIF2RX1" }, \ + { name, "AIF2RX2", "AIF2RX2" }, \ + { name, "AIF3RX1", "AIF3RX1" }, \ + { name, "AIF3RX2", "AIF3RX2" }, \ + { name, "SLIMRX1", "SLIMRX1" }, \ + { name, "SLIMRX2", "SLIMRX2" }, \ + { name, "SLIMRX3", "SLIMRX3" }, \ + { name, "SLIMRX4", "SLIMRX4" }, \ + { name, "SLIMRX5", "SLIMRX5" }, \ + { name, "SLIMRX6", "SLIMRX6" }, \ + { name, "EQ1", "EQ1" }, \ + { name, "EQ2", "EQ2" }, \ + { name, "EQ3", "EQ3" }, \ + { name, "EQ4", "EQ4" }, \ + { name, "DRC1L", "DRC1L" }, \ + { name, "DRC1R", "DRC1R" }, \ + { name, "DRC2L", "DRC2L" }, \ + { name, "DRC2R", "DRC2R" }, \ + { name, "LHPF1", "LHPF1" }, \ + { name, "LHPF2", "LHPF2" }, \ + { name, "LHPF3", "LHPF3" }, \ + { name, "LHPF4", "LHPF4" }, \ + { name, "ISRC1DEC1", "ISRC1DEC1" }, \ + { name, "ISRC1DEC2", "ISRC1DEC2" }, \ + { name, "ISRC1DEC3", "ISRC1DEC3" }, \ + { name, "ISRC1DEC4", "ISRC1DEC4" }, \ + { name, "ISRC1INT1", "ISRC1INT1" }, \ + { name, "ISRC1INT2", "ISRC1INT2" }, \ + { name, "ISRC1INT3", "ISRC1INT3" }, \ + { name, "ISRC1INT4", "ISRC1INT4" }, \ + { name, "ISRC2DEC1", "ISRC2DEC1" }, \ + { name, "ISRC2DEC2", "ISRC2DEC2" }, \ + { name, "ISRC2DEC3", "ISRC2DEC3" }, \ + { name, "ISRC2DEC4", "ISRC2DEC4" }, \ + { name, "ISRC2INT1", "ISRC2INT1" }, \ + { name, "ISRC2INT2", "ISRC2INT2" }, \ + { name, "ISRC2INT3", "ISRC2INT3" }, \ + { name, "ISRC2INT4", "ISRC2INT4" }, \ + { name, "DSP1.1", "DSP1" }, \ + { name, "DSP1.2", "DSP1" }, \ + { name, "DSP1.3", "DSP1" }, \ + { name, "DSP1.4", "DSP1" }, \ + { name, "DSP1.5", "DSP1" }, \ + { name, "DSP1.6", "DSP1" }, \ + { name, "DSP2.1", "DSP2" }, \ + { name, "DSP2.2", "DSP2" }, \ + { name, "DSP2.3", "DSP2" }, \ + { name, "DSP2.4", "DSP2" }, \ + { name, "DSP2.5", "DSP2" }, \ + { name, "DSP2.6", "DSP2" }, \ + { name, "DSP3.1", "DSP3" }, \ + { name, "DSP3.2", "DSP3" }, \ + { name, "DSP3.3", "DSP3" }, \ + { name, "DSP3.4", "DSP3" }, \ + { name, "DSP3.5", "DSP3" }, \ + { name, "DSP3.6", "DSP3" } + +static const struct snd_soc_dapm_route cs47l35_dapm_routes[] = { + /* Internal clock domains */ + { "EQ1", NULL, "FXCLK" }, + { "EQ2", NULL, "FXCLK" }, + { "EQ3", NULL, "FXCLK" }, + { "EQ4", NULL, "FXCLK" }, + { "DRC1L", NULL, "FXCLK" }, + { "DRC1R", NULL, "FXCLK" }, + { "DRC2L", NULL, "FXCLK" }, + { "DRC2R", NULL, "FXCLK" }, + { "LHPF1", NULL, "FXCLK" }, + { "LHPF2", NULL, "FXCLK" }, + { "LHPF3", NULL, "FXCLK" }, + { "LHPF4", NULL, "FXCLK" }, + { "PWM1 Mixer", NULL, "PWMCLK" }, + { "PWM2 Mixer", NULL, "PWMCLK" }, + { "OUT1L", NULL, "OUTCLK" }, + { "OUT1R", NULL, "OUTCLK" }, + { "OUT4L", NULL, "OUTCLK" }, + { "OUT5L", NULL, "OUTCLK" }, + { "OUT5R", NULL, "OUTCLK" }, + { "AIF1TX1", NULL, "AIF1TXCLK" }, + { "AIF1TX2", NULL, "AIF1TXCLK" }, + { "AIF1TX3", NULL, "AIF1TXCLK" }, + { "AIF1TX4", NULL, "AIF1TXCLK" }, + { "AIF1TX5", NULL, "AIF1TXCLK" }, + { "AIF1TX6", NULL, "AIF1TXCLK" }, + { "AIF2TX1", NULL, "AIF2TXCLK" }, + { "AIF2TX2", NULL, "AIF2TXCLK" }, + { "AIF3TX1", NULL, "AIF3TXCLK" }, + { "AIF3TX2", NULL, "AIF3TXCLK" }, + { "SLIMTX1", NULL, "SLIMBUSCLK" }, + { "SLIMTX2", NULL, "SLIMBUSCLK" }, + { "SLIMTX3", NULL, "SLIMBUSCLK" }, + { "SLIMTX4", NULL, "SLIMBUSCLK" }, + { "SLIMTX5", NULL, "SLIMBUSCLK" }, + { "SLIMTX6", NULL, "SLIMBUSCLK" }, + { "SPD1TX1", NULL, "SPDCLK" }, + { "SPD1TX2", NULL, "SPDCLK" }, + { "DSP1", NULL, "DSP1CLK" }, + { "DSP2", NULL, "DSP2CLK" }, + { "DSP3", NULL, "DSP3CLK" }, + { "ISRC1DEC1", NULL, "ISRC1CLK" }, + { "ISRC1DEC2", NULL, "ISRC1CLK" }, + { "ISRC1DEC3", NULL, "ISRC1CLK" }, + { "ISRC1DEC4", NULL, "ISRC1CLK" }, + { "ISRC1INT1", NULL, "ISRC1CLK" }, + { "ISRC1INT2", NULL, "ISRC1CLK" }, + { "ISRC1INT3", NULL, "ISRC1CLK" }, + { "ISRC1INT4", NULL, "ISRC1CLK" }, + { "ISRC2DEC1", NULL, "ISRC2CLK" }, + { "ISRC2DEC2", NULL, "ISRC2CLK" }, + { "ISRC2DEC3", NULL, "ISRC2CLK" }, + { "ISRC2DEC4", NULL, "ISRC2CLK" }, + { "ISRC2INT1", NULL, "ISRC2CLK" }, + { "ISRC2INT2", NULL, "ISRC2CLK" }, + { "ISRC2INT3", NULL, "ISRC2CLK" }, + { "ISRC2INT4", NULL, "ISRC2CLK" }, + + { "AIF2 Capture", NULL, "DBVDD2" }, + { "AIF2 Playback", NULL, "DBVDD2" }, + + { "AIF3 Capture", NULL, "DBVDD2" }, + { "AIF3 Playback", NULL, "DBVDD2" }, + + { "OUT1L", NULL, "CPVDD1" }, + { "OUT1R", NULL, "CPVDD1" }, + { "OUT1L", NULL, "CPVDD2" }, + { "OUT1R", NULL, "CPVDD2" }, + + { "OUT4L", NULL, "SPKVDD" }, + + { "OUT1L", NULL, "SYSCLK" }, + { "OUT1R", NULL, "SYSCLK" }, + { "OUT4L", NULL, "SYSCLK" }, + { "OUT5L", NULL, "SYSCLK" }, + { "OUT5R", NULL, "SYSCLK" }, + + { "SPD1", NULL, "SYSCLK" }, + { "SPD1", NULL, "SPD1TX1" }, + { "SPD1", NULL, "SPD1TX2" }, + + { "IN1L", NULL, "SYSCLK" }, + { "IN1R", NULL, "SYSCLK" }, + { "IN2L", NULL, "SYSCLK" }, + { "IN2R", NULL, "SYSCLK" }, + + { "MICBIAS1", NULL, "MICVDD" }, + { "MICBIAS2", NULL, "MICVDD" }, + + { "MICBIAS1A", NULL, "MICBIAS1" }, + { "MICBIAS1B", NULL, "MICBIAS1" }, + { "MICBIAS2A", NULL, "MICBIAS2" }, + { "MICBIAS2B", NULL, "MICBIAS2" }, + + { "Noise Generator", NULL, "SYSCLK" }, + { "Tone Generator 1", NULL, "SYSCLK" }, + { "Tone Generator 2", NULL, "SYSCLK" }, + + { "Noise Generator", NULL, "NOISE" }, + { "Tone Generator 1", NULL, "TONE" }, + { "Tone Generator 2", NULL, "TONE" }, + + { "AIF1 Capture", NULL, "AIF1TX1" }, + { "AIF1 Capture", NULL, "AIF1TX2" }, + { "AIF1 Capture", NULL, "AIF1TX3" }, + { "AIF1 Capture", NULL, "AIF1TX4" }, + { "AIF1 Capture", NULL, "AIF1TX5" }, + { "AIF1 Capture", NULL, "AIF1TX6" }, + + { "AIF1RX1", NULL, "AIF1 Playback" }, + { "AIF1RX2", NULL, "AIF1 Playback" }, + { "AIF1RX3", NULL, "AIF1 Playback" }, + { "AIF1RX4", NULL, "AIF1 Playback" }, + { "AIF1RX5", NULL, "AIF1 Playback" }, + { "AIF1RX6", NULL, "AIF1 Playback" }, + + { "AIF2 Capture", NULL, "AIF2TX1" }, + { "AIF2 Capture", NULL, "AIF2TX2" }, + + { "AIF2RX1", NULL, "AIF2 Playback" }, + { "AIF2RX2", NULL, "AIF2 Playback" }, + + { "AIF3 Capture", NULL, "AIF3TX1" }, + { "AIF3 Capture", NULL, "AIF3TX2" }, + + { "AIF3RX1", NULL, "AIF3 Playback" }, + { "AIF3RX2", NULL, "AIF3 Playback" }, + + { "Slim1 Capture", NULL, "SLIMTX1" }, + { "Slim1 Capture", NULL, "SLIMTX2" }, + { "Slim1 Capture", NULL, "SLIMTX3" }, + { "Slim1 Capture", NULL, "SLIMTX4" }, + + { "SLIMRX1", NULL, "Slim1 Playback" }, + { "SLIMRX2", NULL, "Slim1 Playback" }, + { "SLIMRX3", NULL, "Slim1 Playback" }, + { "SLIMRX4", NULL, "Slim1 Playback" }, + + { "Slim2 Capture", NULL, "SLIMTX5" }, + { "Slim2 Capture", NULL, "SLIMTX6" }, + + { "SLIMRX5", NULL, "Slim2 Playback" }, + { "SLIMRX6", NULL, "Slim2 Playback" }, + + { "AIF1 Playback", NULL, "SYSCLK" }, + { "AIF2 Playback", NULL, "SYSCLK" }, + { "AIF3 Playback", NULL, "SYSCLK" }, + { "Slim1 Playback", NULL, "SYSCLK" }, + { "Slim2 Playback", NULL, "SYSCLK" }, + + { "AIF1 Capture", NULL, "SYSCLK" }, + { "AIF2 Capture", NULL, "SYSCLK" }, + { "AIF3 Capture", NULL, "SYSCLK" }, + { "Slim1 Capture", NULL, "SYSCLK" }, + { "Slim2 Capture", NULL, "SYSCLK" }, + + { "Voice Control DSP", NULL, "DSP3" }, + + { "Audio Trace DSP", NULL, "DSP1" }, + + { "IN1L Analog Mux", "A", "IN1ALN" }, + { "IN1L Analog Mux", "A", "IN1ALP" }, + { "IN1L Analog Mux", "B", "IN1BLN" }, + { "IN1L Analog Mux", "B", "IN1BLP" }, + + { "IN1R Analog Mux", "A", "IN1ARN" }, + { "IN1R Analog Mux", "A", "IN1ARP" }, + { "IN1R Analog Mux", "B", "IN1BRN" }, + { "IN1R Analog Mux", "B", "IN1BRP" }, + + { "IN1L Mode", "Analog", "IN1L Analog Mux" }, + { "IN1R Mode", "Analog", "IN1R Analog Mux" }, + + { "IN1L Mode", "Digital", "IN1ALN" }, + { "IN1L Mode", "Digital", "IN1ARN" }, + { "IN1R Mode", "Digital", "IN1ALN" }, + { "IN1R Mode", "Digital", "IN1ARN" }, + + { "IN1L", NULL, "IN1L Mode" }, + { "IN1R", NULL, "IN1R Mode" }, + + { "IN2L Mode", "Analog", "IN2LN" }, + { "IN2L Mode", "Analog", "IN2LP" }, + { "IN2R Mode", "Analog", "IN2RN" }, + { "IN2R Mode", "Analog", "IN2RP" }, + + { "IN2L Mode", "Digital", "IN2LN" }, + { "IN2L Mode", "Digital", "IN2RN" }, + { "IN2R Mode", "Digital", "IN2LN" }, + { "IN2R Mode", "Digital", "IN2RN" }, + + { "IN2L", NULL, "IN2L Mode" }, + { "IN2R", NULL, "IN2R Mode" }, + + MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"), + MADERA_MIXER_ROUTES("OUT1R", "HPOUT1R"), + + MADERA_MIXER_ROUTES("OUT4L", "SPKOUT"), + + MADERA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), + MADERA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), + + MADERA_MIXER_ROUTES("PWM1 Driver", "PWM1"), + MADERA_MIXER_ROUTES("PWM2 Driver", "PWM2"), + + MADERA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), + MADERA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), + MADERA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), + MADERA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), + MADERA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), + MADERA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), + + MADERA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), + MADERA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), + + MADERA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), + MADERA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), + + MADERA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), + MADERA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), + MADERA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), + MADERA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), + MADERA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), + MADERA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), + + MADERA_MUX_ROUTES("SPD1TX1", "SPDIF1TX1"), + MADERA_MUX_ROUTES("SPD1TX2", "SPDIF1TX2"), + + MADERA_MIXER_ROUTES("EQ1", "EQ1"), + MADERA_MIXER_ROUTES("EQ2", "EQ2"), + MADERA_MIXER_ROUTES("EQ3", "EQ3"), + MADERA_MIXER_ROUTES("EQ4", "EQ4"), + + MADERA_MIXER_ROUTES("DRC1L", "DRC1L"), + MADERA_MIXER_ROUTES("DRC1R", "DRC1R"), + MADERA_MIXER_ROUTES("DRC2L", "DRC2L"), + MADERA_MIXER_ROUTES("DRC2R", "DRC2R"), + + MADERA_MIXER_ROUTES("LHPF1", "LHPF1"), + MADERA_MIXER_ROUTES("LHPF2", "LHPF2"), + MADERA_MIXER_ROUTES("LHPF3", "LHPF3"), + MADERA_MIXER_ROUTES("LHPF4", "LHPF4"), + + MADERA_DSP_ROUTES("DSP1"), + MADERA_DSP_ROUTES("DSP2"), + MADERA_DSP_ROUTES("DSP3"), + + { "DSP Trigger Out", NULL, "DSP1 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP2 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP3 Trigger Output" }, + + { "DSP1 Trigger Output", "Switch", "DSP1" }, + { "DSP2 Trigger Output", "Switch", "DSP2" }, + { "DSP3 Trigger Output", "Switch", "DSP3" }, + + MADERA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), + MADERA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), + MADERA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), + MADERA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), + + MADERA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), + MADERA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), + MADERA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), + MADERA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), + + MADERA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), + MADERA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), + MADERA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"), + MADERA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"), + + MADERA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), + MADERA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), + MADERA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"), + MADERA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"), + + { "AEC1 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC1 Loopback", "HPOUT1R", "OUT1R" }, + { "AEC2 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC2 Loopback", "HPOUT1R", "OUT1R" }, + { "HPOUT1 Demux", NULL, "OUT1L" }, + { "HPOUT1 Demux", NULL, "OUT1R" }, + + { "AEC1 Loopback", "SPKOUT", "OUT4L" }, + { "AEC2 Loopback", "SPKOUT", "OUT4L" }, + { "SPKOUTN", NULL, "OUT4L" }, + { "SPKOUTP", NULL, "OUT4L" }, + + { "HPOUTL", "HPOUT", "HPOUT1 Demux" }, + { "HPOUTR", "HPOUT", "HPOUT1 Demux" }, + { "EPOUTP", "EPOUT", "HPOUT1 Demux" }, + { "EPOUTN", "EPOUT", "HPOUT1 Demux" }, + + { "AEC1 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC1 Loopback", "SPKDAT1R", "OUT5R" }, + { "AEC2 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC2 Loopback", "SPKDAT1R", "OUT5R" }, + { "SPKDAT1L", NULL, "OUT5L" }, + { "SPKDAT1R", NULL, "OUT5R" }, + + { "SPDIF1", NULL, "SPD1" }, + + { "MICSUPP", NULL, "SYSCLK" }, + + { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" }, + { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" }, + { "DRC1 Activity Output", "Switch", "DRC1L" }, + { "DRC1 Activity Output", "Switch", "DRC1R" }, + { "DRC2 Activity Output", "Switch", "DRC2L" }, + { "DRC2 Activity Output", "Switch", "DRC2R" }, +}; + +static int cs47l35_set_fll(struct snd_soc_component *component, int fll_id, + int source, unsigned int fref, unsigned int fout) +{ + struct cs47l35 *cs47l35 = snd_soc_component_get_drvdata(component); + + switch (fll_id) { + case MADERA_FLL1_REFCLK: + return madera_set_fll_refclk(&cs47l35->fll, source, fref, + fout); + case MADERA_FLL1_SYNCCLK: + return madera_set_fll_syncclk(&cs47l35->fll, source, fref, + fout); + default: + return -EINVAL; + } +} + +static struct snd_soc_dai_driver cs47l35_dai[] = { + { + .name = "cs47l35-aif1", + .id = 1, + .base = MADERA_AIF1_BCLK_CTRL, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l35-aif2", + .id = 2, + .base = MADERA_AIF2_BCLK_CTRL, + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l35-aif3", + .id = 3, + .base = MADERA_AIF3_BCLK_CTRL, + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l35-slim1", + .id = 4, + .playback = { + .stream_name = "Slim1 Playback", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim1 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l35-slim2", + .id = 5, + .playback = { + .stream_name = "Slim2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l35-cpu-voicectrl", + .capture = { + .stream_name = "Voice Control CPU", + .channels_min = 1, + .channels_max = 1, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .compress_new = &snd_soc_new_compress, + }, + { + .name = "cs47l35-dsp-voicectrl", + .capture = { + .stream_name = "Voice Control DSP", + .channels_min = 1, + .channels_max = 1, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + }, + { + .name = "cs47l35-cpu-trace", + .capture = { + .stream_name = "Audio Trace CPU", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .compress_new = &snd_soc_new_compress, + }, + { + .name = "cs47l35-dsp-trace", + .capture = { + .stream_name = "Audio Trace DSP", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + }, +}; + +static int cs47l35_open(struct snd_compr_stream *stream) +{ + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, DRV_NAME); + struct cs47l35 *cs47l35 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l35->core; + struct madera *madera = priv->madera; + int n_adsp; + + if (strcmp(rtd->codec_dai->name, "cs47l35-dsp-voicectrl") == 0) { + n_adsp = 2; + } else if (strcmp(rtd->codec_dai->name, "cs47l35-dsp-trace") == 0) { + n_adsp = 0; + } else { + dev_err(madera->dev, + "No suitable compressed stream for DAI '%s'\n", + rtd->codec_dai->name); + return -EINVAL; + } + + return wm_adsp_compr_open(&priv->adsp[n_adsp], stream); +} + +static irqreturn_t cs47l35_adsp2_irq(int irq, void *data) +{ + struct cs47l35 *cs47l35 = data; + struct madera_priv *priv = &cs47l35->core; + struct madera *madera = priv->madera; + struct madera_voice_trigger_info trig_info; + int serviced = 0; + int i, ret; + + for (i = 0; i < CS47L35_NUM_ADSP; ++i) { + ret = wm_adsp_compr_handle_irq(&priv->adsp[i]); + if (ret != -ENODEV) + serviced++; + if (ret == WM_ADSP_COMPR_VOICE_TRIGGER) { + trig_info.core_num = i + 1; + blocking_notifier_call_chain(&madera->notifier, + MADERA_NOTIFY_VOICE_TRIGGER, + &trig_info); + } + } + + if (!serviced) { + dev_err(madera->dev, "Spurious compressed data IRQ\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +static int cs47l35_component_probe(struct snd_soc_component *component) +{ + struct cs47l35 *cs47l35 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l35->core.madera; + int i, ret; + + snd_soc_component_init_regmap(component, madera->regmap); + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = snd_soc_component_get_dapm(component); + mutex_unlock(&madera->dapm_ptr_lock); + + ret = madera_init_inputs(component); + if (ret) + return ret; + + ret = madera_init_outputs(component, CS47L35_MONO_OUTPUTS); + if (ret) + return ret; + + snd_soc_component_disable_pin(component, "HAPTICS"); + + ret = snd_soc_add_component_controls(component, + madera_adsp_rate_controls, + CS47L35_NUM_ADSP); + if (ret) + return ret; + + for (i = 0; i < CS47L35_NUM_ADSP; i++) + wm_adsp2_component_probe(&cs47l35->core.adsp[i], component); + + return 0; +} + +static void cs47l35_component_remove(struct snd_soc_component *component) +{ + struct cs47l35 *cs47l35 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l35->core.madera; + int i; + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = NULL; + mutex_unlock(&madera->dapm_ptr_lock); + + for (i = 0; i < CS47L35_NUM_ADSP; i++) + wm_adsp2_component_remove(&cs47l35->core.adsp[i], component); +} + +#define CS47L35_DIG_VU 0x0200 + +static unsigned int cs47l35_digital_vu[] = { + MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, + MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, +}; + +static const struct snd_compr_ops cs47l35_compr_ops = { + .open = &cs47l35_open, + .free = &wm_adsp_compr_free, + .set_params = &wm_adsp_compr_set_params, + .get_caps = &wm_adsp_compr_get_caps, + .trigger = &wm_adsp_compr_trigger, + .pointer = &wm_adsp_compr_pointer, + .copy = &wm_adsp_compr_copy, +}; + +static const struct snd_soc_component_driver soc_component_dev_cs47l35 = { + .probe = &cs47l35_component_probe, + .remove = &cs47l35_component_remove, + .set_sysclk = &madera_set_sysclk, + .set_pll = &cs47l35_set_fll, + .name = DRV_NAME, + .compr_ops = &cs47l35_compr_ops, + .controls = cs47l35_snd_controls, + .num_controls = ARRAY_SIZE(cs47l35_snd_controls), + .dapm_widgets = cs47l35_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs47l35_dapm_widgets), + .dapm_routes = cs47l35_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs47l35_dapm_routes), + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static int cs47l35_probe(struct platform_device *pdev) +{ + struct madera *madera = dev_get_drvdata(pdev->dev.parent); + struct cs47l35 *cs47l35; + int i, ret; + + BUILD_BUG_ON(ARRAY_SIZE(cs47l35_dai) > MADERA_MAX_DAI); + + /* quick exit if Madera irqchip driver hasn't completed probe */ + if (!madera->irq_dev) { + dev_dbg(&pdev->dev, "irqchip driver not ready\n"); + return -EPROBE_DEFER; + } + + cs47l35 = devm_kzalloc(&pdev->dev, sizeof(struct cs47l35), GFP_KERNEL); + if (!cs47l35) + return -ENOMEM; + platform_set_drvdata(pdev, cs47l35); + + cs47l35->core.madera = madera; + cs47l35->core.dev = &pdev->dev; + cs47l35->core.num_inputs = 4; + + ret = madera_core_init(&cs47l35->core); + if (ret) + return ret; + + ret = madera_init_overheat(&cs47l35->core); + if (ret) + goto error_core; + + ret = madera_request_irq(madera, MADERA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", cs47l35_adsp2_irq, + cs47l35); + if (ret) { + dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); + goto error_overheat; + } + + ret = madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 1); + if (ret) + dev_warn(&pdev->dev, "Failed to set DSP IRQ wake: %d\n", ret); + + for (i = 0; i < CS47L35_NUM_ADSP; i++) { + cs47l35->core.adsp[i].part = "cs47l35"; + cs47l35->core.adsp[i].num = i + 1; + cs47l35->core.adsp[i].type = WMFW_ADSP2; + cs47l35->core.adsp[i].rev = 1; + cs47l35->core.adsp[i].dev = madera->dev; + cs47l35->core.adsp[i].regmap = madera->regmap_32bit; + + cs47l35->core.adsp[i].base = wm_adsp2_control_bases[i]; + cs47l35->core.adsp[i].mem = cs47l35_dsp_regions[i]; + cs47l35->core.adsp[i].num_mems = + ARRAY_SIZE(cs47l35_dsp1_regions); + + ret = wm_adsp2_init(&cs47l35->core.adsp[i]); + if (ret) { + for (--i; i >= 0; --i) + wm_adsp2_remove(&cs47l35->core.adsp[i]); + goto error_dsp_irq; + } + } + + madera_init_fll(madera, 1, MADERA_FLL1_CONTROL_1 - 1, &cs47l35->fll); + + for (i = 0; i < ARRAY_SIZE(cs47l35_dai); i++) + madera_init_dai(&cs47l35->core, i); + + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(cs47l35_digital_vu); i++) + regmap_update_bits(madera->regmap, cs47l35_digital_vu[i], + CS47L35_DIG_VU, CS47L35_DIG_VU); + + pm_runtime_enable(&pdev->dev); + pm_runtime_idle(&pdev->dev); + + ret = devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_cs47l35, + cs47l35_dai, + ARRAY_SIZE(cs47l35_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register component: %d\n", ret); + goto error_pm_runtime; + } + + return ret; + +error_pm_runtime: + pm_runtime_disable(&pdev->dev); + + for (i = 0; i < CS47L35_NUM_ADSP; i++) + wm_adsp2_remove(&cs47l35->core.adsp[i]); +error_dsp_irq: + madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(madera, MADERA_IRQ_DSP_IRQ1, cs47l35); +error_overheat: + madera_free_overheat(&cs47l35->core); +error_core: + madera_core_free(&cs47l35->core); + + return ret; +} + +static int cs47l35_remove(struct platform_device *pdev) +{ + struct cs47l35 *cs47l35 = platform_get_drvdata(pdev); + int i; + + pm_runtime_disable(&pdev->dev); + + for (i = 0; i < CS47L35_NUM_ADSP; i++) + wm_adsp2_remove(&cs47l35->core.adsp[i]); + + madera_set_irq_wake(cs47l35->core.madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(cs47l35->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l35); + madera_free_overheat(&cs47l35->core); + madera_core_free(&cs47l35->core); + + return 0; +} + +static struct platform_driver cs47l35_codec_driver = { + .driver = { + .name = "cs47l35-codec", + }, + .probe = &cs47l35_probe, + .remove = &cs47l35_remove, +}; + +module_platform_driver(cs47l35_codec_driver); + +MODULE_SOFTDEP("pre: madera irq-madera arizona-micsupp"); +MODULE_DESCRIPTION("ASoC CS47L35 driver"); +MODULE_AUTHOR("Piotr Stankiewicz "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:cs47l35-codec"); From 95a9049b5854d21420a782a41e3f79619655c2bc Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 19 Jun 2019 14:41:58 +0100 Subject: [PATCH 478/626] ASoC: cs47l85: Add codec driver for Cirrus Logic CS47L85 Adds the codec driver for the CS47L85 SmartCodec. This is a multi-functional codec based on the Cirrus Logic Madera platform. Signed-off-by: Nariman Poushin Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/cs47l85.c | 2734 ++++++++++++++++++++++++++++++++++++ 3 files changed, 2742 insertions(+) create mode 100644 sound/soc/codecs/cs47l85.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 5b3f7775510c..a8aa801b9342 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -71,6 +71,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS4349 if I2C select SND_SOC_CS47L24 if MFD_CS47L24 select SND_SOC_CS47L35 if MFD_CS47L35 + select SND_SOC_CS47L85 if MFD_CS47L85 select SND_SOC_CS53L30 if I2C select SND_SOC_CX20442 if TTY select SND_SOC_CX2072X if I2C @@ -583,6 +584,9 @@ config SND_SOC_CS47L24 config SND_SOC_CS47L35 tristate +config SND_SOC_CS47L85 + tristate + # Cirrus Logic Quad-Channel ADC config SND_SOC_CS53L30 tristate "Cirrus Logic CS53L30 CODEC" @@ -713,7 +717,9 @@ config SND_SOC_LOCHNAGAR_SC config SND_SOC_MADERA tristate default y if SND_SOC_CS47L35=y + default y if SND_SOC_CS47L85=y default m if SND_SOC_CS47L35=m + default m if SND_SOC_CS47L85=m config SND_SOC_MAX98088 tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 55239f0bfad0..ce02d1fb250b 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -66,6 +66,7 @@ snd-soc-cs4341-objs := cs4341.o snd-soc-cs4349-objs := cs4349.o snd-soc-cs47l24-objs := cs47l24.o snd-soc-cs47l35-objs := cs47l35.o +snd-soc-cs47l85-objs := cs47l85.o snd-soc-cs53l30-objs := cs53l30.o snd-soc-cx20442-objs := cx20442.o snd-soc-cx2072x-objs := cx2072x.o @@ -344,6 +345,7 @@ obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o +obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c new file mode 100644 index 000000000000..4c4bae6e2c57 --- /dev/null +++ b/sound/soc/codecs/cs47l85.c @@ -0,0 +1,2734 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// ALSA SoC Audio driver for CS47L85 codec +// +// Copyright (C) 2015-2019 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by the +// Free Software Foundation; version 2. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "madera.h" +#include "wm_adsp.h" + +#define DRV_NAME "cs47l85-codec" + +#define CS47L85_NUM_ADSP 7 +#define CS47L85_MONO_OUTPUTS 4 + +struct cs47l85 { + struct madera_priv core; + struct madera_fll fll[3]; +}; + +static const struct wm_adsp_region cs47l85_dsp1_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x080000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x0e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x0a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x0c0000 }, +}; + +static const struct wm_adsp_region cs47l85_dsp2_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x100000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x160000 }, + { .type = WMFW_ADSP2_XM, .base = 0x120000 }, + { .type = WMFW_ADSP2_YM, .base = 0x140000 }, +}; + +static const struct wm_adsp_region cs47l85_dsp3_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x180000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x1e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x1a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x1c0000 }, +}; + +static const struct wm_adsp_region cs47l85_dsp4_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x200000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x260000 }, + { .type = WMFW_ADSP2_XM, .base = 0x220000 }, + { .type = WMFW_ADSP2_YM, .base = 0x240000 }, +}; + +static const struct wm_adsp_region cs47l85_dsp5_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x280000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x2e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x2a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x2c0000 }, +}; + +static const struct wm_adsp_region cs47l85_dsp6_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x300000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x360000 }, + { .type = WMFW_ADSP2_XM, .base = 0x320000 }, + { .type = WMFW_ADSP2_YM, .base = 0x340000 }, +}; + +static const struct wm_adsp_region cs47l85_dsp7_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x380000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x3e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x3a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x3c0000 }, +}; + +static const struct wm_adsp_region *cs47l85_dsp_regions[] = { + cs47l85_dsp1_regions, + cs47l85_dsp2_regions, + cs47l85_dsp3_regions, + cs47l85_dsp4_regions, + cs47l85_dsp5_regions, + cs47l85_dsp6_regions, + cs47l85_dsp7_regions, +}; + +static const unsigned int wm_adsp2_control_bases[] = { + MADERA_DSP1_CONFIG_1, + MADERA_DSP2_CONFIG_1, + MADERA_DSP3_CONFIG_1, + MADERA_DSP4_CONFIG_1, + MADERA_DSP5_CONFIG_1, + MADERA_DSP6_CONFIG_1, + MADERA_DSP7_CONFIG_1, +}; + +static int cs47l85_adsp_power_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct cs47l85 *cs47l85 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l85->core; + struct madera *madera = priv->madera; + unsigned int freq; + int ret; + + ret = regmap_read(madera->regmap, MADERA_DSP_CLOCK_1, &freq); + if (ret != 0) { + dev_err(madera->dev, + "Failed to read MADERA_DSP_CLOCK_1: %d\n", ret); + return ret; + } + + freq &= MADERA_DSP_CLK_FREQ_LEGACY_MASK; + freq >>= MADERA_DSP_CLK_FREQ_LEGACY_SHIFT; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = madera_set_adsp_clk(&cs47l85->core, w->shift, freq); + if (ret) + return ret; + break; + default: + break; + } + + return wm_adsp_early_event(w, kcontrol, event); +} + +#define CS47L85_NG_SRC(name, base) \ + SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ + SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ + SOC_SINGLE(name " NG HPOUT2L Switch", base, 2, 1, 0), \ + SOC_SINGLE(name " NG HPOUT2R Switch", base, 3, 1, 0), \ + SOC_SINGLE(name " NG HPOUT3L Switch", base, 4, 1, 0), \ + SOC_SINGLE(name " NG HPOUT3R Switch", base, 5, 1, 0), \ + SOC_SINGLE(name " NG SPKOUTL Switch", base, 6, 1, 0), \ + SOC_SINGLE(name " NG SPKOUTR Switch", base, 7, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT2L Switch", base, 10, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0) + +#define CS47L85_RXANC_INPUT_ROUTES(widget, name) \ + { widget, NULL, name " NG Mux" }, \ + { name " NG Internal", NULL, "RXANC NG Clock" }, \ + { name " NG Internal", NULL, name " Channel" }, \ + { name " NG External", NULL, "RXANC NG External Clock" }, \ + { name " NG External", NULL, name " Channel" }, \ + { name " NG Mux", "None", name " Channel" }, \ + { name " NG Mux", "Internal", name " NG Internal" }, \ + { name " NG Mux", "External", name " NG External" }, \ + { name " Channel", "Left", name " Left Input" }, \ + { name " Channel", "Combine", name " Left Input" }, \ + { name " Channel", "Right", name " Right Input" }, \ + { name " Channel", "Combine", name " Right Input" }, \ + { name " Left Input", "IN1", "IN1L" }, \ + { name " Right Input", "IN1", "IN1R" }, \ + { name " Left Input", "IN2", "IN2L" }, \ + { name " Right Input", "IN2", "IN2R" }, \ + { name " Left Input", "IN3", "IN3L" }, \ + { name " Right Input", "IN3", "IN3R" }, \ + { name " Left Input", "IN4", "IN4L" }, \ + { name " Right Input", "IN4", "IN4R" }, \ + { name " Left Input", "IN5", "IN5L" }, \ + { name " Right Input", "IN5", "IN5R" }, \ + { name " Left Input", "IN6", "IN6L" }, \ + { name " Right Input", "IN6", "IN6R" } + +#define CS47L85_RXANC_OUTPUT_ROUTES(widget, name) \ + { widget, NULL, name " ANC Source" }, \ + { name " ANC Source", "RXANCL", "RXANCL" }, \ + { name " ANC Source", "RXANCR", "RXANCR" } + +static void cs47l85_hp_post_enable(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + unsigned int val; + int ret; + + switch (w->shift) { + case MADERA_OUT1L_ENA_SHIFT: + case MADERA_OUT1R_ENA_SHIFT: + ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, + &val); + if (ret) { + dev_err(component->dev, + "Failed to check output enables: %d\n", ret); + return; + } + + val &= (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA); + + if (val != (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA)) + break; + + snd_soc_component_update_bits(component, + MADERA_EDRE_HP_STEREO_CONTROL, + 0x0001, 1); + break; + default: + break; + } +} + +static void cs47l85_hp_post_disable(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + switch (w->shift) { + case MADERA_OUT1L_ENA_SHIFT: + snd_soc_component_write(component, MADERA_DCS_HP1L_CONTROL, + 0x2006); + break; + case MADERA_OUT1R_ENA_SHIFT: + snd_soc_component_write(component, MADERA_DCS_HP1R_CONTROL, + 0x2006); + break; + default: + return; + } + + /* Only get to here for OUT1L and OUT1R */ + snd_soc_component_update_bits(component, + MADERA_EDRE_HP_STEREO_CONTROL, + 0x0001, 0); +} + +static int cs47l85_hp_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + case SND_SOC_DAPM_PRE_PMD: + return madera_hp_ev(w, kcontrol, event); + case SND_SOC_DAPM_POST_PMU: + ret = madera_hp_ev(w, kcontrol, event); + if (ret < 0) + return ret; + + cs47l85_hp_post_enable(w); + return 0; + case SND_SOC_DAPM_POST_PMD: + ret = madera_hp_ev(w, kcontrol, event); + cs47l85_hp_post_disable(w); + return ret; + default: + return -EINVAL; + } +} + +static const struct snd_kcontrol_new cs47l85_snd_controls[] = { +SOC_ENUM("IN1 OSR", madera_in_dmic_osr[0]), +SOC_ENUM("IN2 OSR", madera_in_dmic_osr[1]), +SOC_ENUM("IN3 OSR", madera_in_dmic_osr[2]), +SOC_ENUM("IN4 OSR", madera_in_dmic_osr[3]), +SOC_ENUM("IN5 OSR", madera_in_dmic_osr[4]), +SOC_ENUM("IN6 OSR", madera_in_dmic_osr[5]), + +SOC_SINGLE_RANGE_TLV("IN1L Volume", MADERA_IN1L_CONTROL, + MADERA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN1R Volume", MADERA_IN1R_CONTROL, + MADERA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2L Volume", MADERA_IN2L_CONTROL, + MADERA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2R Volume", MADERA_IN2R_CONTROL, + MADERA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN3L Volume", MADERA_IN3L_CONTROL, + MADERA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN3R Volume", MADERA_IN3R_CONTROL, + MADERA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), + +SOC_ENUM("IN HPF Cutoff Frequency", madera_in_hpf_cut_enum), + +SOC_SINGLE("IN1L HPF Switch", MADERA_IN1L_CONTROL, + MADERA_IN1L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN1R HPF Switch", MADERA_IN1R_CONTROL, + MADERA_IN1R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2L HPF Switch", MADERA_IN2L_CONTROL, + MADERA_IN2L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2R HPF Switch", MADERA_IN2R_CONTROL, + MADERA_IN2R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN3L HPF Switch", MADERA_IN3L_CONTROL, + MADERA_IN3L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN3R HPF Switch", MADERA_IN3R_CONTROL, + MADERA_IN3R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN4L HPF Switch", MADERA_IN4L_CONTROL, + MADERA_IN4L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN4R HPF Switch", MADERA_IN4R_CONTROL, + MADERA_IN4R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN5L HPF Switch", MADERA_IN5L_CONTROL, + MADERA_IN5L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN5R HPF Switch", MADERA_IN5R_CONTROL, + MADERA_IN5R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN6L HPF Switch", MADERA_IN6L_CONTROL, + MADERA_IN6L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN6R HPF Switch", MADERA_IN6R_CONTROL, + MADERA_IN6R_HPF_SHIFT, 1, 0), + +SOC_SINGLE_TLV("IN1L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1L, + MADERA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN1R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1R, + MADERA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2L, + MADERA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2R, + MADERA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN3L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_3L, + MADERA_IN3L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN3R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_3R, + MADERA_IN3R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN4L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_4L, + MADERA_IN4L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN4R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_4R, + MADERA_IN4R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN5L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_5L, + MADERA_IN5L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN5R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_5R, + MADERA_IN5R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN6L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_6L, + MADERA_IN6L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN6R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_6R, + MADERA_IN6R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), + +SOC_ENUM("Input Ramp Up", madera_in_vi_ramp), +SOC_ENUM("Input Ramp Down", madera_in_vd_ramp), + +SND_SOC_BYTES("RXANC Coefficients", MADERA_ANC_COEFF_START, + MADERA_ANC_COEFF_END - MADERA_ANC_COEFF_START + 1), +SND_SOC_BYTES("RXANCL Config", MADERA_FCL_FILTER_CONTROL, 1), +SND_SOC_BYTES("RXANCL Coefficients", MADERA_FCL_COEFF_START, + MADERA_FCL_COEFF_END - MADERA_FCL_COEFF_START + 1), +SND_SOC_BYTES("RXANCR Config", MADERA_FCR_FILTER_CONTROL, 1), +SND_SOC_BYTES("RXANCR Coefficients", MADERA_FCR_COEFF_START, + MADERA_FCR_COEFF_END - MADERA_FCR_COEFF_START + 1), + +MADERA_MIXER_CONTROLS("EQ1", MADERA_EQ1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ2", MADERA_EQ2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ3", MADERA_EQ3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ4", MADERA_EQ4MIX_INPUT_1_SOURCE), + +MADERA_EQ_CONTROL("EQ1 Coefficients", MADERA_EQ1_2), +SOC_SINGLE_TLV("EQ1 B1 Volume", MADERA_EQ1_1, MADERA_EQ1_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B2 Volume", MADERA_EQ1_1, MADERA_EQ1_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B3 Volume", MADERA_EQ1_1, MADERA_EQ1_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B4 Volume", MADERA_EQ1_2, MADERA_EQ1_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B5 Volume", MADERA_EQ1_2, MADERA_EQ1_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ2 Coefficients", MADERA_EQ2_2), +SOC_SINGLE_TLV("EQ2 B1 Volume", MADERA_EQ2_1, MADERA_EQ2_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B2 Volume", MADERA_EQ2_1, MADERA_EQ2_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B3 Volume", MADERA_EQ2_1, MADERA_EQ2_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B4 Volume", MADERA_EQ2_2, MADERA_EQ2_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B5 Volume", MADERA_EQ2_2, MADERA_EQ2_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ3 Coefficients", MADERA_EQ3_2), +SOC_SINGLE_TLV("EQ3 B1 Volume", MADERA_EQ3_1, MADERA_EQ3_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B2 Volume", MADERA_EQ3_1, MADERA_EQ3_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B3 Volume", MADERA_EQ3_1, MADERA_EQ3_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B4 Volume", MADERA_EQ3_2, MADERA_EQ3_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B5 Volume", MADERA_EQ3_2, MADERA_EQ3_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ4 Coefficients", MADERA_EQ4_2), +SOC_SINGLE_TLV("EQ4 B1 Volume", MADERA_EQ4_1, MADERA_EQ4_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B2 Volume", MADERA_EQ4_1, MADERA_EQ4_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B3 Volume", MADERA_EQ4_1, MADERA_EQ4_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B4 Volume", MADERA_EQ4_2, MADERA_EQ4_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B5 Volume", MADERA_EQ4_2, MADERA_EQ4_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_MIXER_CONTROLS("DRC1L", MADERA_DRC1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC1R", MADERA_DRC1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2L", MADERA_DRC2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2R", MADERA_DRC2RMIX_INPUT_1_SOURCE), + +SND_SOC_BYTES_MASK("DRC1", MADERA_DRC1_CTRL1, 5, + MADERA_DRC1R_ENA | MADERA_DRC1L_ENA), +SND_SOC_BYTES_MASK("DRC2", MADERA_DRC2_CTRL1, 5, + MADERA_DRC2R_ENA | MADERA_DRC2L_ENA), + +MADERA_MIXER_CONTROLS("LHPF1", MADERA_HPLP1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF2", MADERA_HPLP2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF3", MADERA_HPLP3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF4", MADERA_HPLP4MIX_INPUT_1_SOURCE), + +MADERA_LHPF_CONTROL("LHPF1 Coefficients", MADERA_HPLPF1_2), +MADERA_LHPF_CONTROL("LHPF2 Coefficients", MADERA_HPLPF2_2), +MADERA_LHPF_CONTROL("LHPF3 Coefficients", MADERA_HPLPF3_2), +MADERA_LHPF_CONTROL("LHPF4 Coefficients", MADERA_HPLPF4_2), + +SOC_ENUM("LHPF1 Mode", madera_lhpf1_mode), +SOC_ENUM("LHPF2 Mode", madera_lhpf2_mode), +SOC_ENUM("LHPF3 Mode", madera_lhpf3_mode), +SOC_ENUM("LHPF4 Mode", madera_lhpf4_mode), + +MADERA_RATE_ENUM("ISRC1 FSL", madera_isrc_fsl[0]), +MADERA_RATE_ENUM("ISRC2 FSL", madera_isrc_fsl[1]), +MADERA_RATE_ENUM("ISRC3 FSL", madera_isrc_fsl[2]), +MADERA_RATE_ENUM("ISRC4 FSL", madera_isrc_fsl[3]), +MADERA_RATE_ENUM("ISRC1 FSH", madera_isrc_fsh[0]), +MADERA_RATE_ENUM("ISRC2 FSH", madera_isrc_fsh[1]), +MADERA_RATE_ENUM("ISRC3 FSH", madera_isrc_fsh[2]), +MADERA_RATE_ENUM("ISRC4 FSH", madera_isrc_fsh[3]), +MADERA_RATE_ENUM("ASRC1 Rate 1", madera_asrc1_rate[0]), +MADERA_RATE_ENUM("ASRC1 Rate 2", madera_asrc1_rate[1]), +MADERA_RATE_ENUM("ASRC2 Rate 1", madera_asrc2_rate[0]), +MADERA_RATE_ENUM("ASRC2 Rate 2", madera_asrc2_rate[1]), + +WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), +WM_ADSP2_PRELOAD_SWITCH("DSP2", 2), +WM_ADSP2_PRELOAD_SWITCH("DSP3", 3), +WM_ADSP2_PRELOAD_SWITCH("DSP4", 4), +WM_ADSP2_PRELOAD_SWITCH("DSP5", 5), +WM_ADSP2_PRELOAD_SWITCH("DSP6", 6), +WM_ADSP2_PRELOAD_SWITCH("DSP7", 7), + +MADERA_MIXER_CONTROLS("DSP1L", MADERA_DSP1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP1R", MADERA_DSP1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP2L", MADERA_DSP2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP2R", MADERA_DSP2RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP3L", MADERA_DSP3LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP3R", MADERA_DSP3RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP4L", MADERA_DSP4LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP4R", MADERA_DSP4RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP5L", MADERA_DSP5LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP5R", MADERA_DSP5RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP6L", MADERA_DSP6LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP6R", MADERA_DSP6RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP7L", MADERA_DSP7LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP7R", MADERA_DSP7RMIX_INPUT_1_SOURCE), + +SOC_SINGLE_TLV("Noise Generator Volume", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, madera_noise_tlv), + +MADERA_MIXER_CONTROLS("HPOUT1L", MADERA_OUT1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT1R", MADERA_OUT1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT2L", MADERA_OUT2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT2R", MADERA_OUT2RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT3L", MADERA_OUT3LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT3R", MADERA_OUT3RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKOUTL", MADERA_OUT4LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKOUTR", MADERA_OUT4RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1L", MADERA_OUT5LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1R", MADERA_OUT5RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT2L", MADERA_OUT6LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT2R", MADERA_OUT6RMIX_INPUT_1_SOURCE), + +SOC_SINGLE("HPOUT1 SC Protect Switch", MADERA_HP1_SHORT_CIRCUIT_CTRL, + MADERA_HP1_SC_ENA_SHIFT, 1, 0), +SOC_SINGLE("HPOUT2 SC Protect Switch", MADERA_HP2_SHORT_CIRCUIT_CTRL, + MADERA_HP2_SC_ENA_SHIFT, 1, 0), +SOC_SINGLE("HPOUT3 SC Protect Switch", MADERA_HP3_SHORT_CIRCUIT_CTRL, + MADERA_HP3_SC_ENA_SHIFT, 1, 0), + +SOC_SINGLE("SPKDAT1 High Performance Switch", MADERA_OUTPUT_PATH_CONFIG_5L, + MADERA_OUT5_OSR_SHIFT, 1, 0), +SOC_SINGLE("SPKDAT2 High Performance Switch", MADERA_OUTPUT_PATH_CONFIG_6L, + MADERA_OUT6_OSR_SHIFT, 1, 0), + +SOC_DOUBLE_R("HPOUT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("HPOUT2 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, MADERA_OUT2L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("HPOUT3 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, MADERA_OUT3L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("Speaker Digital Switch", MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_DAC_DIGITAL_VOLUME_4R, MADERA_OUT4L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT2 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_6L, + MADERA_DAC_DIGITAL_VOLUME_6R, MADERA_OUT6L_MUTE_SHIFT, 1, 1), + +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, MADERA_OUT2L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, MADERA_OUT3L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("Speaker Digital Volume", MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_DAC_DIGITAL_VOLUME_4R, MADERA_OUT4L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_6L, + MADERA_DAC_DIGITAL_VOLUME_6R, MADERA_OUT6L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), + +SOC_DOUBLE("SPKDAT1 Switch", MADERA_PDM_SPK1_CTRL_1, MADERA_SPK1L_MUTE_SHIFT, + MADERA_SPK1R_MUTE_SHIFT, 1, 1), +SOC_DOUBLE("SPKDAT2 Switch", MADERA_PDM_SPK2_CTRL_1, MADERA_SPK2L_MUTE_SHIFT, + MADERA_SPK2R_MUTE_SHIFT, 1, 1), + +SOC_ENUM("Output Ramp Up", madera_out_vi_ramp), +SOC_ENUM("Output Ramp Down", madera_out_vd_ramp), + +SOC_SINGLE("Noise Gate Switch", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_ENA_SHIFT, 1, 0), +SOC_SINGLE_TLV("Noise Gate Threshold Volume", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_THR_SHIFT, 7, 1, madera_ng_tlv), +SOC_ENUM("Noise Gate Hold", madera_ng_hold), + +CS47L85_NG_SRC("HPOUT1L", MADERA_NOISE_GATE_SELECT_1L), +CS47L85_NG_SRC("HPOUT1R", MADERA_NOISE_GATE_SELECT_1R), +CS47L85_NG_SRC("HPOUT2L", MADERA_NOISE_GATE_SELECT_2L), +CS47L85_NG_SRC("HPOUT2R", MADERA_NOISE_GATE_SELECT_2R), +CS47L85_NG_SRC("HPOUT3L", MADERA_NOISE_GATE_SELECT_3L), +CS47L85_NG_SRC("HPOUT3R", MADERA_NOISE_GATE_SELECT_3R), +CS47L85_NG_SRC("SPKOUTL", MADERA_NOISE_GATE_SELECT_4L), +CS47L85_NG_SRC("SPKOUTR", MADERA_NOISE_GATE_SELECT_4R), +CS47L85_NG_SRC("SPKDAT1L", MADERA_NOISE_GATE_SELECT_5L), +CS47L85_NG_SRC("SPKDAT1R", MADERA_NOISE_GATE_SELECT_5R), +CS47L85_NG_SRC("SPKDAT2L", MADERA_NOISE_GATE_SELECT_6L), +CS47L85_NG_SRC("SPKDAT2R", MADERA_NOISE_GATE_SELECT_6R), + +MADERA_MIXER_CONTROLS("AIF1TX1", MADERA_AIF1TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX2", MADERA_AIF1TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX3", MADERA_AIF1TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX4", MADERA_AIF1TX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX5", MADERA_AIF1TX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX6", MADERA_AIF1TX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX7", MADERA_AIF1TX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX8", MADERA_AIF1TX8MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF2TX1", MADERA_AIF2TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX2", MADERA_AIF2TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX3", MADERA_AIF2TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX4", MADERA_AIF2TX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX5", MADERA_AIF2TX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX6", MADERA_AIF2TX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX7", MADERA_AIF2TX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX8", MADERA_AIF2TX8MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF3TX1", MADERA_AIF3TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF3TX2", MADERA_AIF3TX2MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF4TX1", MADERA_AIF4TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF4TX2", MADERA_AIF4TX2MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("SLIMTX1", MADERA_SLIMTX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX2", MADERA_SLIMTX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX3", MADERA_SLIMTX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX4", MADERA_SLIMTX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX5", MADERA_SLIMTX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX6", MADERA_SLIMTX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX7", MADERA_SLIMTX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX8", MADERA_SLIMTX8MIX_INPUT_1_SOURCE), + +MADERA_GAINMUX_CONTROLS("SPDIF1TX1", MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE), +MADERA_GAINMUX_CONTROLS("SPDIF1TX2", MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP1", 0), +WM_ADSP_FW_CONTROL("DSP2", 1), +WM_ADSP_FW_CONTROL("DSP3", 2), +WM_ADSP_FW_CONTROL("DSP4", 3), +WM_ADSP_FW_CONTROL("DSP5", 4), +WM_ADSP_FW_CONTROL("DSP6", 5), +WM_ADSP_FW_CONTROL("DSP7", 6), +}; + +MADERA_MIXER_ENUMS(EQ1, MADERA_EQ1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ2, MADERA_EQ2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ3, MADERA_EQ3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ4, MADERA_EQ4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DRC1L, MADERA_DRC1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC1R, MADERA_DRC1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2L, MADERA_DRC2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2R, MADERA_DRC2RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(LHPF1, MADERA_HPLP1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF2, MADERA_HPLP2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF3, MADERA_HPLP3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF4, MADERA_HPLP4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP1L, MADERA_DSP1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP1R, MADERA_DSP1RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP1, MADERA_DSP1AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP2L, MADERA_DSP2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP2R, MADERA_DSP2RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP2, MADERA_DSP2AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP3L, MADERA_DSP3LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP3R, MADERA_DSP3RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP3, MADERA_DSP3AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP4L, MADERA_DSP4LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP4R, MADERA_DSP4RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP4, MADERA_DSP4AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP5L, MADERA_DSP5LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP5R, MADERA_DSP5RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP5, MADERA_DSP5AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP6L, MADERA_DSP6LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP6R, MADERA_DSP6RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP6, MADERA_DSP6AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP7L, MADERA_DSP7LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP7R, MADERA_DSP7RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP7, MADERA_DSP7AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(PWM1, MADERA_PWM1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(PWM2, MADERA_PWM2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(OUT1L, MADERA_OUT1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT1R, MADERA_OUT1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT2L, MADERA_OUT2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT2R, MADERA_OUT2RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT3L, MADERA_OUT3LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT3R, MADERA_OUT3RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKOUTL, MADERA_OUT4LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKOUTR, MADERA_OUT4RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1L, MADERA_OUT5LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1R, MADERA_OUT5RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT2L, MADERA_OUT6LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT2R, MADERA_OUT6RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF1TX1, MADERA_AIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX2, MADERA_AIF1TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX3, MADERA_AIF1TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX4, MADERA_AIF1TX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX5, MADERA_AIF1TX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX6, MADERA_AIF1TX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX7, MADERA_AIF1TX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX8, MADERA_AIF1TX8MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF2TX1, MADERA_AIF2TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX2, MADERA_AIF2TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX3, MADERA_AIF2TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX4, MADERA_AIF2TX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX5, MADERA_AIF2TX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX6, MADERA_AIF2TX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX7, MADERA_AIF2TX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX8, MADERA_AIF2TX8MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF3TX1, MADERA_AIF3TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF3TX2, MADERA_AIF3TX2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF4TX1, MADERA_AIF4TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF4TX2, MADERA_AIF4TX2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(SLIMTX1, MADERA_SLIMTX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX2, MADERA_SLIMTX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX3, MADERA_SLIMTX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX4, MADERA_SLIMTX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX5, MADERA_SLIMTX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX6, MADERA_SLIMTX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX7, MADERA_SLIMTX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX8, MADERA_SLIMTX8MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(SPD1TX1, MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(SPD1TX2, MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ASRC1IN1L, MADERA_ASRC1_1LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN1R, MADERA_ASRC1_1RMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN2L, MADERA_ASRC1_2LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN2R, MADERA_ASRC1_2RMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC2IN1L, MADERA_ASRC2_1LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC2IN1R, MADERA_ASRC2_1RMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC2IN2L, MADERA_ASRC2_2LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC2IN2R, MADERA_ASRC2_2RMIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1INT1, MADERA_ISRC1INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT2, MADERA_ISRC1INT2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT3, MADERA_ISRC1INT3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT4, MADERA_ISRC1INT4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1DEC1, MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC2, MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC3, MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC4, MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2INT1, MADERA_ISRC2INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT2, MADERA_ISRC2INT2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT3, MADERA_ISRC2INT3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT4, MADERA_ISRC2INT4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2DEC1, MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC2, MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC3, MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC4, MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC3INT1, MADERA_ISRC3INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC3INT2, MADERA_ISRC3INT2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC3DEC1, MADERA_ISRC3DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC3DEC2, MADERA_ISRC3DEC2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC4INT1, MADERA_ISRC4INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC4INT2, MADERA_ISRC4INT2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC4DEC1, MADERA_ISRC4DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC4DEC2, MADERA_ISRC4DEC2MIX_INPUT_1_SOURCE); + +static const char * const cs47l85_aec_loopback_texts[] = { + "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", + "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R", +}; + +static const unsigned int cs47l85_aec_loopback_values[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +}; + +static const struct soc_enum cs47l85_aec1_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l85_aec_loopback_texts), + cs47l85_aec_loopback_texts, + cs47l85_aec_loopback_values); + +static const struct soc_enum cs47l85_aec2_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_2, + MADERA_AEC2_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l85_aec_loopback_texts), + cs47l85_aec_loopback_texts, + cs47l85_aec_loopback_values); + +static const struct snd_kcontrol_new cs47l85_aec_loopback_mux[] = { + SOC_DAPM_ENUM("AEC1 Loopback", cs47l85_aec1_loopback), + SOC_DAPM_ENUM("AEC2 Loopback", cs47l85_aec2_loopback), +}; + +static const struct snd_kcontrol_new cs47l85_anc_input_mux[] = { + SOC_DAPM_ENUM("RXANCL Input", madera_anc_input_src[0]), + SOC_DAPM_ENUM("RXANCL Channel", madera_anc_input_src[1]), + SOC_DAPM_ENUM("RXANCR Input", madera_anc_input_src[2]), + SOC_DAPM_ENUM("RXANCR Channel", madera_anc_input_src[3]), +}; + +static const struct snd_kcontrol_new cs47l85_anc_ng_mux = + SOC_DAPM_ENUM("RXANC NG Source", madera_anc_ng_enum); + +static const struct snd_kcontrol_new cs47l85_output_anc_src[] = { + SOC_DAPM_ENUM("HPOUT1L ANC Source", madera_output_anc_src[0]), + SOC_DAPM_ENUM("HPOUT1R ANC Source", madera_output_anc_src[1]), + SOC_DAPM_ENUM("HPOUT2L ANC Source", madera_output_anc_src[2]), + SOC_DAPM_ENUM("HPOUT2R ANC Source", madera_output_anc_src[3]), + SOC_DAPM_ENUM("HPOUT3L ANC Source", madera_output_anc_src[4]), + SOC_DAPM_ENUM("HPOUT3R ANC Source", madera_output_anc_src[5]), + SOC_DAPM_ENUM("SPKOUTL ANC Source", madera_output_anc_src[6]), + SOC_DAPM_ENUM("SPKOUTR ANC Source", madera_output_anc_src[7]), + SOC_DAPM_ENUM("SPKDAT1L ANC Source", madera_output_anc_src[8]), + SOC_DAPM_ENUM("SPKDAT1R ANC Source", madera_output_anc_src[9]), + SOC_DAPM_ENUM("SPKDAT2L ANC Source", madera_output_anc_src[10]), + SOC_DAPM_ENUM("SPKDAT2R ANC Source", madera_output_anc_src[11]), +}; + +static const struct snd_soc_dapm_widget cs47l85_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, + 0, madera_sysclk_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, + MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, + MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, + MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, + MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD4", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD2", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS1", MADERA_MIC_BIAS_CTRL_1, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", MADERA_MIC_BIAS_CTRL_2, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS3", MADERA_MIC_BIAS_CTRL_3, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS4", MADERA_MIC_BIAS_CTRL_4, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("FXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_FX, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ASRC1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ASRC1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ASRC2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ASRC2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC3CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC4CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC4, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_OUT, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SPD, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP3CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP4CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP4, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP5CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP5, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP6CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP6, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP7CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP7, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF1TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF2TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF3TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF4TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF4, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SLIMBUSCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SLIMBUS, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("PWMCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_PWM, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + +SND_SOC_DAPM_SUPPLY("RXANC NG External Clock", SND_SOC_NOPM, + MADERA_EXT_NG_SEL_SET_SHIFT, 0, madera_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + +SND_SOC_DAPM_SUPPLY("RXANC NG Clock", SND_SOC_NOPM, + MADERA_CLK_NG_ENA_SET_SHIFT, 0, madera_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + +SND_SOC_DAPM_SIGGEN("TONE"), +SND_SOC_DAPM_SIGGEN("NOISE"), + +SND_SOC_DAPM_INPUT("IN1ALN"), +SND_SOC_DAPM_INPUT("IN1ALP"), +SND_SOC_DAPM_INPUT("IN1BN"), +SND_SOC_DAPM_INPUT("IN1BP"), +SND_SOC_DAPM_INPUT("IN1RN"), +SND_SOC_DAPM_INPUT("IN1RP"), +SND_SOC_DAPM_INPUT("IN2ALN"), +SND_SOC_DAPM_INPUT("IN2ALP"), +SND_SOC_DAPM_INPUT("IN2ARN"), +SND_SOC_DAPM_INPUT("IN2ARP"), +SND_SOC_DAPM_INPUT("IN2BLN"), +SND_SOC_DAPM_INPUT("IN2BLP"), +SND_SOC_DAPM_INPUT("IN2BRN"), +SND_SOC_DAPM_INPUT("IN2BRP"), +SND_SOC_DAPM_INPUT("IN3LN"), +SND_SOC_DAPM_INPUT("IN3LP"), +SND_SOC_DAPM_INPUT("IN3RN"), +SND_SOC_DAPM_INPUT("IN3RP"), +SND_SOC_DAPM_INPUT("DMICCLK4"), +SND_SOC_DAPM_INPUT("DMICDAT4"), +SND_SOC_DAPM_INPUT("DMICCLK5"), +SND_SOC_DAPM_INPUT("DMICDAT5"), +SND_SOC_DAPM_INPUT("DMICCLK6"), +SND_SOC_DAPM_INPUT("DMICDAT6"), + +SND_SOC_DAPM_MUX("IN1L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[0]), +SND_SOC_DAPM_MUX("IN2L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[2]), +SND_SOC_DAPM_MUX("IN2R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[3]), + +SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), +SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), + +SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), +SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), + +SND_SOC_DAPM_MUX("IN3L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[2]), +SND_SOC_DAPM_MUX("IN3R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[2]), + +SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), +SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), + +SND_SOC_DAPM_OUTPUT("DSP Trigger Out"), + +SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_PGA("RXANCL NG External", SND_SOC_NOPM, 0, 0, NULL, 0), +SND_SOC_DAPM_PGA("RXANCR NG External", SND_SOC_NOPM, 0, 0, NULL, 0), + +SND_SOC_DAPM_PGA("RXANCL NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0), +SND_SOC_DAPM_PGA("RXANCR NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0), + +SND_SOC_DAPM_MUX("RXANCL Left Input", SND_SOC_NOPM, 0, 0, + &cs47l85_anc_input_mux[0]), +SND_SOC_DAPM_MUX("RXANCL Right Input", SND_SOC_NOPM, 0, 0, + &cs47l85_anc_input_mux[0]), +SND_SOC_DAPM_MUX("RXANCL Channel", SND_SOC_NOPM, 0, 0, + &cs47l85_anc_input_mux[1]), +SND_SOC_DAPM_MUX("RXANCL NG Mux", SND_SOC_NOPM, 0, 0, &cs47l85_anc_ng_mux), +SND_SOC_DAPM_MUX("RXANCR Left Input", SND_SOC_NOPM, 0, 0, + &cs47l85_anc_input_mux[2]), +SND_SOC_DAPM_MUX("RXANCR Right Input", SND_SOC_NOPM, 0, 0, + &cs47l85_anc_input_mux[2]), +SND_SOC_DAPM_MUX("RXANCR Channel", SND_SOC_NOPM, 0, 0, + &cs47l85_anc_input_mux[3]), +SND_SOC_DAPM_MUX("RXANCR NG Mux", SND_SOC_NOPM, 0, 0, &cs47l85_anc_ng_mux), + +SND_SOC_DAPM_PGA_E("RXANCL", SND_SOC_NOPM, MADERA_CLK_L_ENA_SET_SHIFT, + 0, NULL, 0, madera_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA_E("RXANCR", SND_SOC_NOPM, MADERA_CLK_R_ENA_SET_SHIFT, + 0, NULL, 0, madera_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + +SND_SOC_DAPM_MUX("HPOUT1L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[0]), +SND_SOC_DAPM_MUX("HPOUT1R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[1]), +SND_SOC_DAPM_MUX("HPOUT2L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[2]), +SND_SOC_DAPM_MUX("HPOUT2R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[3]), +SND_SOC_DAPM_MUX("HPOUT3L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[4]), +SND_SOC_DAPM_MUX("HPOUT3R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[5]), +SND_SOC_DAPM_MUX("SPKOUTL ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[6]), +SND_SOC_DAPM_MUX("SPKOUTR ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[7]), +SND_SOC_DAPM_MUX("SPKDAT1L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[8]), +SND_SOC_DAPM_MUX("SPKDAT1R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[9]), +SND_SOC_DAPM_MUX("SPKDAT2L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[10]), +SND_SOC_DAPM_MUX("SPKDAT2R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l85_output_anc_src[11]), + +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF4TX1", NULL, 0, + MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 0, + MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, + MADERA_OUT1L_ENA_SHIFT, 0, NULL, 0, cs47l85_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, + MADERA_OUT1R_ENA_SHIFT, 0, NULL, 0, cs47l85_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT2L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT2R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT3L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT3R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM, + MADERA_OUT4L_ENA_SHIFT, 0, NULL, 0, madera_spk_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM, + MADERA_OUT4R_ENA_SHIFT, 0, NULL, 0, madera_spk_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA_E("OUT5L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT6L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT6L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT6R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT6R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("SPD1TX1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL1_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("SPD1TX2", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL2_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_OUT_DRV("SPD1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_ENA_SHIFT, 0, NULL, 0), + +/* + * Input mux widgets arranged in order of sources in MADERA_MIXER_INPUT_ROUTES + * to take advantage of cache lookup in DAPM + */ +SND_SOC_DAPM_PGA("Noise Generator", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Tone Generator 1", MADERA_TONE_GENERATOR_1, + MADERA_TONE1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("Tone Generator 2", MADERA_TONE_GENERATOR_1, + MADERA_TONE2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SIGGEN("HAPTICS"), + +SND_SOC_DAPM_MUX("AEC1 Loopback", MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_ENA_SHIFT, 0, + &cs47l85_aec_loopback_mux[0]), +SND_SOC_DAPM_MUX("AEC2 Loopback", MADERA_DAC_AEC_CONTROL_2, + MADERA_AEC2_LOOPBACK_ENA_SHIFT, 0, + &cs47l85_aec_loopback_mux[1]), + +SND_SOC_DAPM_PGA_E("IN1L", MADERA_INPUT_ENABLES, MADERA_IN1L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN1R", MADERA_INPUT_ENABLES, MADERA_IN1R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2L", MADERA_INPUT_ENABLES, MADERA_IN2L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3L", MADERA_INPUT_ENABLES, MADERA_IN3L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3R", MADERA_INPUT_ENABLES, MADERA_IN3R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4L", MADERA_INPUT_ENABLES, MADERA_IN4L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4R", MADERA_INPUT_ENABLES, MADERA_IN4R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN5L", MADERA_INPUT_ENABLES, MADERA_IN5L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN5R", MADERA_INPUT_ENABLES, MADERA_IN5R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN6L", MADERA_INPUT_ENABLES, MADERA_IN6L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN6R", MADERA_INPUT_ENABLES, MADERA_IN6R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF4RX1", NULL, 0, + MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 0, + MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, + MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ2", MADERA_EQ2_1, MADERA_EQ2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ3", MADERA_EQ3_1, MADERA_EQ3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ4", MADERA_EQ4_1, MADERA_EQ4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("DRC1L", MADERA_DRC1_CTRL1, MADERA_DRC1L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC1R", MADERA_DRC1_CTRL1, MADERA_DRC1R_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2L", MADERA_DRC2_CTRL1, MADERA_DRC2L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2R", MADERA_DRC2_CTRL1, MADERA_DRC2R_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("LHPF1", MADERA_HPLPF1_1, MADERA_LHPF1_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF2", MADERA_HPLPF2_1, MADERA_LHPF2_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF3", MADERA_HPLPF3_1, MADERA_LHPF3_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF4", MADERA_HPLPF4_1, MADERA_LHPF4_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("ASRC1IN1L", MADERA_ASRC1_ENABLE, MADERA_ASRC1_IN1L_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN1R", MADERA_ASRC1_ENABLE, MADERA_ASRC1_IN1R_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN2L", MADERA_ASRC1_ENABLE, MADERA_ASRC1_IN2L_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN2R", MADERA_ASRC1_ENABLE, MADERA_ASRC1_IN2R_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_PGA("ASRC2IN1L", MADERA_ASRC2_ENABLE, MADERA_ASRC2_IN1L_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC2IN1R", MADERA_ASRC2_ENABLE, MADERA_ASRC2_IN1R_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC2IN2L", MADERA_ASRC2_ENABLE, MADERA_ASRC2_IN2L_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC2IN2R", MADERA_ASRC2_ENABLE, MADERA_ASRC2_IN2R_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1DEC1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC3", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC4", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1INT1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT3", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT4", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2DEC1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC3", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC4", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2INT1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT3", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT4", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC3DEC1", MADERA_ISRC_3_CTRL_3, + MADERA_ISRC3_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC3DEC2", MADERA_ISRC_3_CTRL_3, + MADERA_ISRC3_DEC2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC3INT1", MADERA_ISRC_3_CTRL_3, + MADERA_ISRC3_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC3INT2", MADERA_ISRC_3_CTRL_3, + MADERA_ISRC3_INT2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC4DEC1", MADERA_ISRC_4_CTRL_3, + MADERA_ISRC4_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC4DEC2", MADERA_ISRC_4_CTRL_3, + MADERA_ISRC4_DEC2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC4INT1", MADERA_ISRC_4_CTRL_3, + MADERA_ISRC4_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC4INT2", MADERA_ISRC_4_CTRL_3, + MADERA_ISRC4_INT2_ENA_SHIFT, 0, NULL, 0), + +WM_ADSP2("DSP1", 0, cs47l85_adsp_power_ev), +WM_ADSP2("DSP2", 1, cs47l85_adsp_power_ev), +WM_ADSP2("DSP3", 2, cs47l85_adsp_power_ev), +WM_ADSP2("DSP4", 3, cs47l85_adsp_power_ev), +WM_ADSP2("DSP5", 4, cs47l85_adsp_power_ev), +WM_ADSP2("DSP6", 5, cs47l85_adsp_power_ev), +WM_ADSP2("DSP7", 6, cs47l85_adsp_power_ev), + +/* End of ordered input mux widgets */ + +MADERA_MIXER_WIDGETS(EQ1, "EQ1"), +MADERA_MIXER_WIDGETS(EQ2, "EQ2"), +MADERA_MIXER_WIDGETS(EQ3, "EQ3"), +MADERA_MIXER_WIDGETS(EQ4, "EQ4"), + +MADERA_MIXER_WIDGETS(DRC1L, "DRC1L"), +MADERA_MIXER_WIDGETS(DRC1R, "DRC1R"), +MADERA_MIXER_WIDGETS(DRC2L, "DRC2L"), +MADERA_MIXER_WIDGETS(DRC2R, "DRC2R"), + +SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[0]), +SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[1]), + +MADERA_MIXER_WIDGETS(LHPF1, "LHPF1"), +MADERA_MIXER_WIDGETS(LHPF2, "LHPF2"), +MADERA_MIXER_WIDGETS(LHPF3, "LHPF3"), +MADERA_MIXER_WIDGETS(LHPF4, "LHPF4"), + +MADERA_MIXER_WIDGETS(PWM1, "PWM1"), +MADERA_MIXER_WIDGETS(PWM2, "PWM2"), + +MADERA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), +MADERA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), +MADERA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), +MADERA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), +MADERA_MIXER_WIDGETS(OUT3L, "HPOUT3L"), +MADERA_MIXER_WIDGETS(OUT3R, "HPOUT3R"), +MADERA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), +MADERA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), +MADERA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), +MADERA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), +MADERA_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"), +MADERA_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"), + +MADERA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), +MADERA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), +MADERA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), +MADERA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), +MADERA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), +MADERA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), +MADERA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), +MADERA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), + +MADERA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), +MADERA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), +MADERA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), +MADERA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), +MADERA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"), +MADERA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"), +MADERA_MIXER_WIDGETS(AIF2TX7, "AIF2TX7"), +MADERA_MIXER_WIDGETS(AIF2TX8, "AIF2TX8"), + +MADERA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), +MADERA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), + +MADERA_MIXER_WIDGETS(AIF4TX1, "AIF4TX1"), +MADERA_MIXER_WIDGETS(AIF4TX2, "AIF4TX2"), + +MADERA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), +MADERA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), +MADERA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), +MADERA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), +MADERA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), +MADERA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), +MADERA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), +MADERA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), + +MADERA_MUX_WIDGETS(SPD1TX1, "SPDIF1TX1"), +MADERA_MUX_WIDGETS(SPD1TX2, "SPDIF1TX2"), + +MADERA_MUX_WIDGETS(ASRC1IN1L, "ASRC1IN1L"), +MADERA_MUX_WIDGETS(ASRC1IN1R, "ASRC1IN1R"), +MADERA_MUX_WIDGETS(ASRC1IN2L, "ASRC1IN2L"), +MADERA_MUX_WIDGETS(ASRC1IN2R, "ASRC1IN2R"), +MADERA_MUX_WIDGETS(ASRC2IN1L, "ASRC2IN1L"), +MADERA_MUX_WIDGETS(ASRC2IN1R, "ASRC2IN1R"), +MADERA_MUX_WIDGETS(ASRC2IN2L, "ASRC2IN2L"), +MADERA_MUX_WIDGETS(ASRC2IN2R, "ASRC2IN2R"), + +MADERA_DSP_WIDGETS(DSP1, "DSP1"), +MADERA_DSP_WIDGETS(DSP2, "DSP2"), +MADERA_DSP_WIDGETS(DSP3, "DSP3"), +MADERA_DSP_WIDGETS(DSP4, "DSP4"), +MADERA_DSP_WIDGETS(DSP5, "DSP5"), +MADERA_DSP_WIDGETS(DSP6, "DSP6"), +MADERA_DSP_WIDGETS(DSP7, "DSP7"), + +SND_SOC_DAPM_SWITCH("DSP1 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[0]), +SND_SOC_DAPM_SWITCH("DSP2 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[1]), +SND_SOC_DAPM_SWITCH("DSP3 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[2]), +SND_SOC_DAPM_SWITCH("DSP4 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[3]), +SND_SOC_DAPM_SWITCH("DSP5 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[4]), +SND_SOC_DAPM_SWITCH("DSP6 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[5]), +SND_SOC_DAPM_SWITCH("DSP7 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[6]), + +MADERA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), +MADERA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), +MADERA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), +MADERA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), + +MADERA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), +MADERA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), +MADERA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), +MADERA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), + +MADERA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), +MADERA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), +MADERA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"), +MADERA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"), + +MADERA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), +MADERA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), +MADERA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"), +MADERA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"), + +MADERA_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"), +MADERA_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"), + +MADERA_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"), +MADERA_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"), + +MADERA_MUX_WIDGETS(ISRC4DEC1, "ISRC4DEC1"), +MADERA_MUX_WIDGETS(ISRC4DEC2, "ISRC4DEC2"), + +MADERA_MUX_WIDGETS(ISRC4INT1, "ISRC4INT1"), +MADERA_MUX_WIDGETS(ISRC4INT2, "ISRC4INT2"), + +SND_SOC_DAPM_OUTPUT("HPOUT1L"), +SND_SOC_DAPM_OUTPUT("HPOUT1R"), +SND_SOC_DAPM_OUTPUT("HPOUT2L"), +SND_SOC_DAPM_OUTPUT("HPOUT2R"), +SND_SOC_DAPM_OUTPUT("HPOUT3L"), +SND_SOC_DAPM_OUTPUT("HPOUT3R"), +SND_SOC_DAPM_OUTPUT("SPKOUTLN"), +SND_SOC_DAPM_OUTPUT("SPKOUTLP"), +SND_SOC_DAPM_OUTPUT("SPKOUTRN"), +SND_SOC_DAPM_OUTPUT("SPKOUTRP"), +SND_SOC_DAPM_OUTPUT("SPKDAT1L"), +SND_SOC_DAPM_OUTPUT("SPKDAT1R"), +SND_SOC_DAPM_OUTPUT("SPKDAT2L"), +SND_SOC_DAPM_OUTPUT("SPKDAT2R"), +SND_SOC_DAPM_OUTPUT("SPDIF1"), + +SND_SOC_DAPM_OUTPUT("MICSUPP"), +}; + +#define MADERA_MIXER_INPUT_ROUTES(name) \ + { name, "Noise Generator", "Noise Generator" }, \ + { name, "Tone Generator 1", "Tone Generator 1" }, \ + { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "Haptics", "HAPTICS" }, \ + { name, "AEC1", "AEC1 Loopback" }, \ + { name, "AEC2", "AEC2 Loopback" }, \ + { name, "IN1L", "IN1L" }, \ + { name, "IN1R", "IN1R" }, \ + { name, "IN2L", "IN2L" }, \ + { name, "IN2R", "IN2R" }, \ + { name, "IN3L", "IN3L" }, \ + { name, "IN3R", "IN3R" }, \ + { name, "IN4L", "IN4L" }, \ + { name, "IN4R", "IN4R" }, \ + { name, "IN5L", "IN5L" }, \ + { name, "IN5R", "IN5R" }, \ + { name, "IN6L", "IN6L" }, \ + { name, "IN6R", "IN6R" }, \ + { name, "AIF1RX1", "AIF1RX1" }, \ + { name, "AIF1RX2", "AIF1RX2" }, \ + { name, "AIF1RX3", "AIF1RX3" }, \ + { name, "AIF1RX4", "AIF1RX4" }, \ + { name, "AIF1RX5", "AIF1RX5" }, \ + { name, "AIF1RX6", "AIF1RX6" }, \ + { name, "AIF1RX7", "AIF1RX7" }, \ + { name, "AIF1RX8", "AIF1RX8" }, \ + { name, "AIF2RX1", "AIF2RX1" }, \ + { name, "AIF2RX2", "AIF2RX2" }, \ + { name, "AIF2RX3", "AIF2RX3" }, \ + { name, "AIF2RX4", "AIF2RX4" }, \ + { name, "AIF2RX5", "AIF2RX5" }, \ + { name, "AIF2RX6", "AIF2RX6" }, \ + { name, "AIF2RX7", "AIF2RX7" }, \ + { name, "AIF2RX8", "AIF2RX8" }, \ + { name, "AIF3RX1", "AIF3RX1" }, \ + { name, "AIF3RX2", "AIF3RX2" }, \ + { name, "AIF4RX1", "AIF4RX1" }, \ + { name, "AIF4RX2", "AIF4RX2" }, \ + { name, "SLIMRX1", "SLIMRX1" }, \ + { name, "SLIMRX2", "SLIMRX2" }, \ + { name, "SLIMRX3", "SLIMRX3" }, \ + { name, "SLIMRX4", "SLIMRX4" }, \ + { name, "SLIMRX5", "SLIMRX5" }, \ + { name, "SLIMRX6", "SLIMRX6" }, \ + { name, "SLIMRX7", "SLIMRX7" }, \ + { name, "SLIMRX8", "SLIMRX8" }, \ + { name, "EQ1", "EQ1" }, \ + { name, "EQ2", "EQ2" }, \ + { name, "EQ3", "EQ3" }, \ + { name, "EQ4", "EQ4" }, \ + { name, "DRC1L", "DRC1L" }, \ + { name, "DRC1R", "DRC1R" }, \ + { name, "DRC2L", "DRC2L" }, \ + { name, "DRC2R", "DRC2R" }, \ + { name, "LHPF1", "LHPF1" }, \ + { name, "LHPF2", "LHPF2" }, \ + { name, "LHPF3", "LHPF3" }, \ + { name, "LHPF4", "LHPF4" }, \ + { name, "ASRC1IN1L", "ASRC1IN1L" }, \ + { name, "ASRC1IN1R", "ASRC1IN1R" }, \ + { name, "ASRC1IN2L", "ASRC1IN2L" }, \ + { name, "ASRC1IN2R", "ASRC1IN2R" }, \ + { name, "ASRC2IN1L", "ASRC2IN1L" }, \ + { name, "ASRC2IN1R", "ASRC2IN1R" }, \ + { name, "ASRC2IN2L", "ASRC2IN2L" }, \ + { name, "ASRC2IN2R", "ASRC2IN2R" }, \ + { name, "ISRC1DEC1", "ISRC1DEC1" }, \ + { name, "ISRC1DEC2", "ISRC1DEC2" }, \ + { name, "ISRC1DEC3", "ISRC1DEC3" }, \ + { name, "ISRC1DEC4", "ISRC1DEC4" }, \ + { name, "ISRC1INT1", "ISRC1INT1" }, \ + { name, "ISRC1INT2", "ISRC1INT2" }, \ + { name, "ISRC1INT3", "ISRC1INT3" }, \ + { name, "ISRC1INT4", "ISRC1INT4" }, \ + { name, "ISRC2DEC1", "ISRC2DEC1" }, \ + { name, "ISRC2DEC2", "ISRC2DEC2" }, \ + { name, "ISRC2DEC3", "ISRC2DEC3" }, \ + { name, "ISRC2DEC4", "ISRC2DEC4" }, \ + { name, "ISRC2INT1", "ISRC2INT1" }, \ + { name, "ISRC2INT2", "ISRC2INT2" }, \ + { name, "ISRC2INT3", "ISRC2INT3" }, \ + { name, "ISRC2INT4", "ISRC2INT4" }, \ + { name, "ISRC3DEC1", "ISRC3DEC1" }, \ + { name, "ISRC3DEC2", "ISRC3DEC2" }, \ + { name, "ISRC3INT1", "ISRC3INT1" }, \ + { name, "ISRC3INT2", "ISRC3INT2" }, \ + { name, "ISRC4DEC1", "ISRC4DEC1" }, \ + { name, "ISRC4DEC2", "ISRC4DEC2" }, \ + { name, "ISRC4INT1", "ISRC4INT1" }, \ + { name, "ISRC4INT2", "ISRC4INT2" }, \ + { name, "DSP1.1", "DSP1" }, \ + { name, "DSP1.2", "DSP1" }, \ + { name, "DSP1.3", "DSP1" }, \ + { name, "DSP1.4", "DSP1" }, \ + { name, "DSP1.5", "DSP1" }, \ + { name, "DSP1.6", "DSP1" }, \ + { name, "DSP2.1", "DSP2" }, \ + { name, "DSP2.2", "DSP2" }, \ + { name, "DSP2.3", "DSP2" }, \ + { name, "DSP2.4", "DSP2" }, \ + { name, "DSP2.5", "DSP2" }, \ + { name, "DSP2.6", "DSP2" }, \ + { name, "DSP3.1", "DSP3" }, \ + { name, "DSP3.2", "DSP3" }, \ + { name, "DSP3.3", "DSP3" }, \ + { name, "DSP3.4", "DSP3" }, \ + { name, "DSP3.5", "DSP3" }, \ + { name, "DSP3.6", "DSP3" }, \ + { name, "DSP4.1", "DSP4" }, \ + { name, "DSP4.2", "DSP4" }, \ + { name, "DSP4.3", "DSP4" }, \ + { name, "DSP4.4", "DSP4" }, \ + { name, "DSP4.5", "DSP4" }, \ + { name, "DSP4.6", "DSP4" }, \ + { name, "DSP5.1", "DSP5" }, \ + { name, "DSP5.2", "DSP5" }, \ + { name, "DSP5.3", "DSP5" }, \ + { name, "DSP5.4", "DSP5" }, \ + { name, "DSP5.5", "DSP5" }, \ + { name, "DSP5.6", "DSP5" }, \ + { name, "DSP6.1", "DSP6" }, \ + { name, "DSP6.2", "DSP6" }, \ + { name, "DSP6.3", "DSP6" }, \ + { name, "DSP6.4", "DSP6" }, \ + { name, "DSP6.5", "DSP6" }, \ + { name, "DSP6.6", "DSP6" }, \ + { name, "DSP7.1", "DSP7" }, \ + { name, "DSP7.2", "DSP7" }, \ + { name, "DSP7.3", "DSP7" }, \ + { name, "DSP7.4", "DSP7" }, \ + { name, "DSP7.5", "DSP7" }, \ + { name, "DSP7.6", "DSP7" } + +static const struct snd_soc_dapm_route cs47l85_dapm_routes[] = { + /* Internal clock domains */ + { "EQ1", NULL, "FXCLK" }, + { "EQ2", NULL, "FXCLK" }, + { "EQ3", NULL, "FXCLK" }, + { "EQ4", NULL, "FXCLK" }, + { "DRC1L", NULL, "FXCLK" }, + { "DRC1R", NULL, "FXCLK" }, + { "DRC2L", NULL, "FXCLK" }, + { "DRC2R", NULL, "FXCLK" }, + { "LHPF1", NULL, "FXCLK" }, + { "LHPF2", NULL, "FXCLK" }, + { "LHPF3", NULL, "FXCLK" }, + { "LHPF4", NULL, "FXCLK" }, + { "PWM1 Mixer", NULL, "PWMCLK" }, + { "PWM2 Mixer", NULL, "PWMCLK" }, + { "OUT1L", NULL, "OUTCLK" }, + { "OUT1R", NULL, "OUTCLK" }, + { "OUT2L", NULL, "OUTCLK" }, + { "OUT2R", NULL, "OUTCLK" }, + { "OUT3L", NULL, "OUTCLK" }, + { "OUT3R", NULL, "OUTCLK" }, + { "OUT4L", NULL, "OUTCLK" }, + { "OUT4R", NULL, "OUTCLK" }, + { "OUT5L", NULL, "OUTCLK" }, + { "OUT5R", NULL, "OUTCLK" }, + { "OUT6L", NULL, "OUTCLK" }, + { "OUT6R", NULL, "OUTCLK" }, + { "AIF1TX1", NULL, "AIF1TXCLK" }, + { "AIF1TX2", NULL, "AIF1TXCLK" }, + { "AIF1TX3", NULL, "AIF1TXCLK" }, + { "AIF1TX4", NULL, "AIF1TXCLK" }, + { "AIF1TX5", NULL, "AIF1TXCLK" }, + { "AIF1TX6", NULL, "AIF1TXCLK" }, + { "AIF1TX7", NULL, "AIF1TXCLK" }, + { "AIF1TX8", NULL, "AIF1TXCLK" }, + { "AIF2TX1", NULL, "AIF2TXCLK" }, + { "AIF2TX2", NULL, "AIF2TXCLK" }, + { "AIF2TX3", NULL, "AIF2TXCLK" }, + { "AIF2TX4", NULL, "AIF2TXCLK" }, + { "AIF2TX5", NULL, "AIF2TXCLK" }, + { "AIF2TX6", NULL, "AIF2TXCLK" }, + { "AIF2TX7", NULL, "AIF2TXCLK" }, + { "AIF2TX8", NULL, "AIF2TXCLK" }, + { "AIF3TX1", NULL, "AIF3TXCLK" }, + { "AIF3TX2", NULL, "AIF3TXCLK" }, + { "AIF4TX1", NULL, "AIF4TXCLK" }, + { "AIF4TX2", NULL, "AIF4TXCLK" }, + { "SLIMTX1", NULL, "SLIMBUSCLK" }, + { "SLIMTX2", NULL, "SLIMBUSCLK" }, + { "SLIMTX3", NULL, "SLIMBUSCLK" }, + { "SLIMTX4", NULL, "SLIMBUSCLK" }, + { "SLIMTX5", NULL, "SLIMBUSCLK" }, + { "SLIMTX6", NULL, "SLIMBUSCLK" }, + { "SLIMTX7", NULL, "SLIMBUSCLK" }, + { "SLIMTX8", NULL, "SLIMBUSCLK" }, + { "SPD1TX1", NULL, "SPDCLK" }, + { "SPD1TX2", NULL, "SPDCLK" }, + { "DSP1", NULL, "DSP1CLK" }, + { "DSP2", NULL, "DSP2CLK" }, + { "DSP3", NULL, "DSP3CLK" }, + { "DSP4", NULL, "DSP4CLK" }, + { "DSP5", NULL, "DSP5CLK" }, + { "DSP6", NULL, "DSP6CLK" }, + { "DSP7", NULL, "DSP7CLK" }, + { "ISRC1DEC1", NULL, "ISRC1CLK" }, + { "ISRC1DEC2", NULL, "ISRC1CLK" }, + { "ISRC1DEC3", NULL, "ISRC1CLK" }, + { "ISRC1DEC4", NULL, "ISRC1CLK" }, + { "ISRC1INT1", NULL, "ISRC1CLK" }, + { "ISRC1INT2", NULL, "ISRC1CLK" }, + { "ISRC1INT3", NULL, "ISRC1CLK" }, + { "ISRC1INT4", NULL, "ISRC1CLK" }, + { "ISRC2DEC1", NULL, "ISRC2CLK" }, + { "ISRC2DEC2", NULL, "ISRC2CLK" }, + { "ISRC2DEC3", NULL, "ISRC2CLK" }, + { "ISRC2DEC4", NULL, "ISRC2CLK" }, + { "ISRC2INT1", NULL, "ISRC2CLK" }, + { "ISRC2INT2", NULL, "ISRC2CLK" }, + { "ISRC2INT3", NULL, "ISRC2CLK" }, + { "ISRC2INT4", NULL, "ISRC2CLK" }, + { "ISRC3DEC1", NULL, "ISRC3CLK" }, + { "ISRC3DEC2", NULL, "ISRC3CLK" }, + { "ISRC3INT1", NULL, "ISRC3CLK" }, + { "ISRC3INT2", NULL, "ISRC3CLK" }, + { "ISRC4DEC1", NULL, "ISRC4CLK" }, + { "ISRC4DEC2", NULL, "ISRC4CLK" }, + { "ISRC4INT1", NULL, "ISRC4CLK" }, + { "ISRC4INT2", NULL, "ISRC4CLK" }, + { "ASRC1IN1L", NULL, "ASRC1CLK" }, + { "ASRC1IN1R", NULL, "ASRC1CLK" }, + { "ASRC1IN2L", NULL, "ASRC1CLK" }, + { "ASRC1IN2R", NULL, "ASRC1CLK" }, + { "ASRC2IN1L", NULL, "ASRC2CLK" }, + { "ASRC2IN1R", NULL, "ASRC2CLK" }, + { "ASRC2IN2L", NULL, "ASRC2CLK" }, + { "ASRC2IN2R", NULL, "ASRC2CLK" }, + + { "AIF2 Capture", NULL, "DBVDD2" }, + { "AIF2 Playback", NULL, "DBVDD2" }, + + { "AIF3 Capture", NULL, "DBVDD3" }, + { "AIF3 Playback", NULL, "DBVDD3" }, + + { "AIF4 Capture", NULL, "DBVDD3" }, + { "AIF4 Playback", NULL, "DBVDD3" }, + + { "OUT1L", NULL, "CPVDD1" }, + { "OUT1L", NULL, "CPVDD2" }, + { "OUT1R", NULL, "CPVDD1" }, + { "OUT1R", NULL, "CPVDD2" }, + { "OUT2L", NULL, "CPVDD1" }, + { "OUT2L", NULL, "CPVDD2" }, + { "OUT2R", NULL, "CPVDD1" }, + { "OUT2R", NULL, "CPVDD2" }, + { "OUT3L", NULL, "CPVDD1" }, + { "OUT3L", NULL, "CPVDD2" }, + { "OUT3R", NULL, "CPVDD1" }, + { "OUT3R", NULL, "CPVDD2" }, + + { "OUT4L", NULL, "SPKVDDL" }, + { "OUT4R", NULL, "SPKVDDR" }, + + { "OUT1L", NULL, "SYSCLK" }, + { "OUT1R", NULL, "SYSCLK" }, + { "OUT2L", NULL, "SYSCLK" }, + { "OUT2R", NULL, "SYSCLK" }, + { "OUT3L", NULL, "SYSCLK" }, + { "OUT3R", NULL, "SYSCLK" }, + { "OUT4L", NULL, "SYSCLK" }, + { "OUT4R", NULL, "SYSCLK" }, + { "OUT5L", NULL, "SYSCLK" }, + { "OUT5R", NULL, "SYSCLK" }, + { "OUT6L", NULL, "SYSCLK" }, + { "OUT6R", NULL, "SYSCLK" }, + + { "SPD1", NULL, "SYSCLK" }, + { "SPD1", NULL, "SPD1TX1" }, + { "SPD1", NULL, "SPD1TX2" }, + + { "IN1L", NULL, "SYSCLK" }, + { "IN1R", NULL, "SYSCLK" }, + { "IN2L", NULL, "SYSCLK" }, + { "IN2R", NULL, "SYSCLK" }, + { "IN3L", NULL, "SYSCLK" }, + { "IN3R", NULL, "SYSCLK" }, + { "IN4L", NULL, "SYSCLK" }, + { "IN4R", NULL, "SYSCLK" }, + { "IN5L", NULL, "SYSCLK" }, + { "IN5R", NULL, "SYSCLK" }, + { "IN6L", NULL, "SYSCLK" }, + { "IN6R", NULL, "SYSCLK" }, + + { "IN4L", NULL, "DBVDD4" }, + { "IN4R", NULL, "DBVDD4" }, + { "IN5L", NULL, "DBVDD4" }, + { "IN5R", NULL, "DBVDD4" }, + { "IN6L", NULL, "DBVDD4" }, + { "IN6R", NULL, "DBVDD4" }, + + { "ASRC1IN1L", NULL, "SYSCLK" }, + { "ASRC1IN1R", NULL, "SYSCLK" }, + { "ASRC1IN2L", NULL, "SYSCLK" }, + { "ASRC1IN2R", NULL, "SYSCLK" }, + { "ASRC2IN1L", NULL, "SYSCLK" }, + { "ASRC2IN1R", NULL, "SYSCLK" }, + { "ASRC2IN2L", NULL, "SYSCLK" }, + { "ASRC2IN2R", NULL, "SYSCLK" }, + + { "ASRC1IN1L", NULL, "ASYNCCLK" }, + { "ASRC1IN1R", NULL, "ASYNCCLK" }, + { "ASRC1IN2L", NULL, "ASYNCCLK" }, + { "ASRC1IN2R", NULL, "ASYNCCLK" }, + { "ASRC2IN1L", NULL, "ASYNCCLK" }, + { "ASRC2IN1R", NULL, "ASYNCCLK" }, + { "ASRC2IN2L", NULL, "ASYNCCLK" }, + { "ASRC2IN2R", NULL, "ASYNCCLK" }, + + { "MICBIAS1", NULL, "MICVDD" }, + { "MICBIAS2", NULL, "MICVDD" }, + { "MICBIAS3", NULL, "MICVDD" }, + { "MICBIAS4", NULL, "MICVDD" }, + + { "Noise Generator", NULL, "SYSCLK" }, + { "Tone Generator 1", NULL, "SYSCLK" }, + { "Tone Generator 2", NULL, "SYSCLK" }, + + { "Noise Generator", NULL, "NOISE" }, + { "Tone Generator 1", NULL, "TONE" }, + { "Tone Generator 2", NULL, "TONE" }, + + { "AIF1 Capture", NULL, "AIF1TX1" }, + { "AIF1 Capture", NULL, "AIF1TX2" }, + { "AIF1 Capture", NULL, "AIF1TX3" }, + { "AIF1 Capture", NULL, "AIF1TX4" }, + { "AIF1 Capture", NULL, "AIF1TX5" }, + { "AIF1 Capture", NULL, "AIF1TX6" }, + { "AIF1 Capture", NULL, "AIF1TX7" }, + { "AIF1 Capture", NULL, "AIF1TX8" }, + + { "AIF1RX1", NULL, "AIF1 Playback" }, + { "AIF1RX2", NULL, "AIF1 Playback" }, + { "AIF1RX3", NULL, "AIF1 Playback" }, + { "AIF1RX4", NULL, "AIF1 Playback" }, + { "AIF1RX5", NULL, "AIF1 Playback" }, + { "AIF1RX6", NULL, "AIF1 Playback" }, + { "AIF1RX7", NULL, "AIF1 Playback" }, + { "AIF1RX8", NULL, "AIF1 Playback" }, + + { "AIF2 Capture", NULL, "AIF2TX1" }, + { "AIF2 Capture", NULL, "AIF2TX2" }, + { "AIF2 Capture", NULL, "AIF2TX3" }, + { "AIF2 Capture", NULL, "AIF2TX4" }, + { "AIF2 Capture", NULL, "AIF2TX5" }, + { "AIF2 Capture", NULL, "AIF2TX6" }, + { "AIF2 Capture", NULL, "AIF2TX7" }, + { "AIF2 Capture", NULL, "AIF2TX8" }, + + { "AIF2RX1", NULL, "AIF2 Playback" }, + { "AIF2RX2", NULL, "AIF2 Playback" }, + { "AIF2RX3", NULL, "AIF2 Playback" }, + { "AIF2RX4", NULL, "AIF2 Playback" }, + { "AIF2RX5", NULL, "AIF2 Playback" }, + { "AIF2RX6", NULL, "AIF2 Playback" }, + { "AIF2RX7", NULL, "AIF2 Playback" }, + { "AIF2RX8", NULL, "AIF2 Playback" }, + + { "AIF3 Capture", NULL, "AIF3TX1" }, + { "AIF3 Capture", NULL, "AIF3TX2" }, + + { "AIF3RX1", NULL, "AIF3 Playback" }, + { "AIF3RX2", NULL, "AIF3 Playback" }, + + { "AIF4 Capture", NULL, "AIF4TX1" }, + { "AIF4 Capture", NULL, "AIF4TX2" }, + + { "AIF4RX1", NULL, "AIF4 Playback" }, + { "AIF4RX2", NULL, "AIF4 Playback" }, + + { "Slim1 Capture", NULL, "SLIMTX1" }, + { "Slim1 Capture", NULL, "SLIMTX2" }, + { "Slim1 Capture", NULL, "SLIMTX3" }, + { "Slim1 Capture", NULL, "SLIMTX4" }, + + { "SLIMRX1", NULL, "Slim1 Playback" }, + { "SLIMRX2", NULL, "Slim1 Playback" }, + { "SLIMRX3", NULL, "Slim1 Playback" }, + { "SLIMRX4", NULL, "Slim1 Playback" }, + + { "Slim2 Capture", NULL, "SLIMTX5" }, + { "Slim2 Capture", NULL, "SLIMTX6" }, + + { "SLIMRX5", NULL, "Slim2 Playback" }, + { "SLIMRX6", NULL, "Slim2 Playback" }, + + { "Slim3 Capture", NULL, "SLIMTX7" }, + { "Slim3 Capture", NULL, "SLIMTX8" }, + + { "SLIMRX7", NULL, "Slim3 Playback" }, + { "SLIMRX8", NULL, "Slim3 Playback" }, + + { "AIF1 Playback", NULL, "SYSCLK" }, + { "AIF2 Playback", NULL, "SYSCLK" }, + { "AIF3 Playback", NULL, "SYSCLK" }, + { "AIF4 Playback", NULL, "SYSCLK" }, + { "Slim1 Playback", NULL, "SYSCLK" }, + { "Slim2 Playback", NULL, "SYSCLK" }, + { "Slim3 Playback", NULL, "SYSCLK" }, + + { "AIF1 Capture", NULL, "SYSCLK" }, + { "AIF2 Capture", NULL, "SYSCLK" }, + { "AIF3 Capture", NULL, "SYSCLK" }, + { "AIF4 Capture", NULL, "SYSCLK" }, + { "Slim1 Capture", NULL, "SYSCLK" }, + { "Slim2 Capture", NULL, "SYSCLK" }, + { "Slim3 Capture", NULL, "SYSCLK" }, + + { "Voice Control DSP", NULL, "DSP6" }, + + { "Audio Trace DSP", NULL, "DSP1" }, + + { "IN1L Analog Mux", "A", "IN1ALN" }, + { "IN1L Analog Mux", "A", "IN1ALP" }, + { "IN1L Analog Mux", "B", "IN1BN" }, + { "IN1L Analog Mux", "B", "IN1BP" }, + + { "IN1L Mode", "Analog", "IN1L Analog Mux" }, + { "IN1R Mode", "Analog", "IN1RN" }, + { "IN1R Mode", "Analog", "IN1RP" }, + + { "IN1L Mode", "Digital", "IN1ALN" }, + { "IN1L Mode", "Digital", "IN1RN" }, + { "IN1R Mode", "Digital", "IN1ALN" }, + { "IN1R Mode", "Digital", "IN1RN" }, + + { "IN1L", NULL, "IN1L Mode" }, + { "IN1R", NULL, "IN1R Mode" }, + + { "IN2L Analog Mux", "A", "IN2ALN" }, + { "IN2L Analog Mux", "A", "IN2ALP" }, + { "IN2L Analog Mux", "B", "IN2BLN" }, + { "IN2L Analog Mux", "B", "IN2BLP" }, + { "IN2R Analog Mux", "A", "IN2ARN" }, + { "IN2R Analog Mux", "A", "IN2ARP" }, + { "IN2R Analog Mux", "B", "IN2BRN" }, + { "IN2R Analog Mux", "B", "IN2BRP" }, + + { "IN2L Mode", "Analog", "IN2L Analog Mux" }, + { "IN2R Mode", "Analog", "IN2R Analog Mux" }, + + { "IN2L Mode", "Digital", "IN2ALN" }, + { "IN2L Mode", "Digital", "IN2ARN" }, + { "IN2R Mode", "Digital", "IN2ALN" }, + { "IN2R Mode", "Digital", "IN2ARN" }, + + { "IN2L", NULL, "IN2L Mode" }, + { "IN2R", NULL, "IN2R Mode" }, + + { "IN3L Mode", "Analog", "IN3LN" }, + { "IN3L Mode", "Analog", "IN3LP" }, + { "IN3R Mode", "Analog", "IN3RN" }, + { "IN3R Mode", "Analog", "IN3RP" }, + + { "IN3L Mode", "Digital", "IN3LN" }, + { "IN3L Mode", "Digital", "IN3RN" }, + { "IN3R Mode", "Digital", "IN3LN" }, + { "IN3R Mode", "Digital", "IN3RN" }, + + { "IN3L", NULL, "IN3L Mode" }, + { "IN3R", NULL, "IN3R Mode" }, + + { "IN4L", NULL, "DMICCLK4" }, + { "IN4R", NULL, "DMICDAT4" }, + + { "IN5L", NULL, "DMICCLK5" }, + { "IN5R", NULL, "DMICDAT5" }, + + { "IN6L", NULL, "DMICCLK6" }, + { "IN6R", NULL, "DMICDAT6" }, + + MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"), + MADERA_MIXER_ROUTES("OUT1R", "HPOUT1R"), + MADERA_MIXER_ROUTES("OUT2L", "HPOUT2L"), + MADERA_MIXER_ROUTES("OUT2R", "HPOUT2R"), + MADERA_MIXER_ROUTES("OUT3L", "HPOUT3L"), + MADERA_MIXER_ROUTES("OUT3R", "HPOUT3R"), + + MADERA_MIXER_ROUTES("OUT4L", "SPKOUTL"), + MADERA_MIXER_ROUTES("OUT4R", "SPKOUTR"), + MADERA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), + MADERA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), + MADERA_MIXER_ROUTES("OUT6L", "SPKDAT2L"), + MADERA_MIXER_ROUTES("OUT6R", "SPKDAT2R"), + + MADERA_MIXER_ROUTES("PWM1 Driver", "PWM1"), + MADERA_MIXER_ROUTES("PWM2 Driver", "PWM2"), + + MADERA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), + MADERA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), + MADERA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), + MADERA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), + MADERA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), + MADERA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), + MADERA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), + MADERA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), + + MADERA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), + MADERA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), + MADERA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), + MADERA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), + MADERA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"), + MADERA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"), + MADERA_MIXER_ROUTES("AIF2TX7", "AIF2TX7"), + MADERA_MIXER_ROUTES("AIF2TX8", "AIF2TX8"), + + MADERA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), + MADERA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), + + MADERA_MIXER_ROUTES("AIF4TX1", "AIF4TX1"), + MADERA_MIXER_ROUTES("AIF4TX2", "AIF4TX2"), + + MADERA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), + MADERA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), + MADERA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), + MADERA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), + MADERA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), + MADERA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), + MADERA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"), + MADERA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"), + + MADERA_MUX_ROUTES("SPD1TX1", "SPDIF1TX1"), + MADERA_MUX_ROUTES("SPD1TX2", "SPDIF1TX2"), + + MADERA_MIXER_ROUTES("EQ1", "EQ1"), + MADERA_MIXER_ROUTES("EQ2", "EQ2"), + MADERA_MIXER_ROUTES("EQ3", "EQ3"), + MADERA_MIXER_ROUTES("EQ4", "EQ4"), + + MADERA_MIXER_ROUTES("DRC1L", "DRC1L"), + MADERA_MIXER_ROUTES("DRC1R", "DRC1R"), + MADERA_MIXER_ROUTES("DRC2L", "DRC2L"), + MADERA_MIXER_ROUTES("DRC2R", "DRC2R"), + + MADERA_MIXER_ROUTES("LHPF1", "LHPF1"), + MADERA_MIXER_ROUTES("LHPF2", "LHPF2"), + MADERA_MIXER_ROUTES("LHPF3", "LHPF3"), + MADERA_MIXER_ROUTES("LHPF4", "LHPF4"), + + MADERA_MUX_ROUTES("ASRC1IN1L", "ASRC1IN1L"), + MADERA_MUX_ROUTES("ASRC1IN1R", "ASRC1IN1R"), + MADERA_MUX_ROUTES("ASRC1IN2L", "ASRC1IN2L"), + MADERA_MUX_ROUTES("ASRC1IN2R", "ASRC1IN2R"), + MADERA_MUX_ROUTES("ASRC2IN1L", "ASRC2IN1L"), + MADERA_MUX_ROUTES("ASRC2IN1R", "ASRC2IN1R"), + MADERA_MUX_ROUTES("ASRC2IN2L", "ASRC2IN2L"), + MADERA_MUX_ROUTES("ASRC2IN2R", "ASRC2IN2R"), + + MADERA_DSP_ROUTES("DSP1"), + MADERA_DSP_ROUTES("DSP2"), + MADERA_DSP_ROUTES("DSP3"), + MADERA_DSP_ROUTES("DSP4"), + MADERA_DSP_ROUTES("DSP5"), + MADERA_DSP_ROUTES("DSP6"), + MADERA_DSP_ROUTES("DSP7"), + + { "DSP Trigger Out", NULL, "DSP1 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP2 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP3 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP4 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP5 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP6 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP7 Trigger Output" }, + + { "DSP1 Trigger Output", "Switch", "DSP1" }, + { "DSP2 Trigger Output", "Switch", "DSP2" }, + { "DSP3 Trigger Output", "Switch", "DSP3" }, + { "DSP4 Trigger Output", "Switch", "DSP4" }, + { "DSP5 Trigger Output", "Switch", "DSP5" }, + { "DSP6 Trigger Output", "Switch", "DSP6" }, + { "DSP7 Trigger Output", "Switch", "DSP7" }, + + MADERA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), + MADERA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), + MADERA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), + MADERA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), + + MADERA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), + MADERA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), + MADERA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), + MADERA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), + + MADERA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), + MADERA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), + MADERA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"), + MADERA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"), + + MADERA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), + MADERA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), + MADERA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"), + MADERA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"), + + MADERA_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"), + MADERA_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"), + + MADERA_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"), + MADERA_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"), + + MADERA_MUX_ROUTES("ISRC4INT1", "ISRC4INT1"), + MADERA_MUX_ROUTES("ISRC4INT2", "ISRC4INT2"), + + MADERA_MUX_ROUTES("ISRC4DEC1", "ISRC4DEC1"), + MADERA_MUX_ROUTES("ISRC4DEC2", "ISRC4DEC2"), + + { "AEC1 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC1 Loopback", "HPOUT1R", "OUT1R" }, + { "AEC2 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC2 Loopback", "HPOUT1R", "OUT1R" }, + { "HPOUT1L", NULL, "OUT1L" }, + { "HPOUT1R", NULL, "OUT1R" }, + + { "AEC1 Loopback", "HPOUT2L", "OUT2L" }, + { "AEC1 Loopback", "HPOUT2R", "OUT2R" }, + { "AEC2 Loopback", "HPOUT2L", "OUT2L" }, + { "AEC2 Loopback", "HPOUT2R", "OUT2R" }, + { "HPOUT2L", NULL, "OUT2L" }, + { "HPOUT2R", NULL, "OUT2R" }, + + { "AEC1 Loopback", "HPOUT3L", "OUT3L" }, + { "AEC1 Loopback", "HPOUT3R", "OUT3R" }, + { "AEC2 Loopback", "HPOUT3L", "OUT3L" }, + { "AEC2 Loopback", "HPOUT3R", "OUT3R" }, + { "HPOUT3L", NULL, "OUT3L" }, + { "HPOUT3R", NULL, "OUT3R" }, + + { "AEC1 Loopback", "SPKOUTL", "OUT4L" }, + { "AEC2 Loopback", "SPKOUTL", "OUT4L" }, + { "SPKOUTLN", NULL, "OUT4L" }, + { "SPKOUTLP", NULL, "OUT4L" }, + + { "AEC1 Loopback", "SPKOUTR", "OUT4R" }, + { "AEC2 Loopback", "SPKOUTR", "OUT4R" }, + { "SPKOUTRN", NULL, "OUT4R" }, + { "SPKOUTRP", NULL, "OUT4R" }, + + { "AEC1 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC1 Loopback", "SPKDAT1R", "OUT5R" }, + { "AEC2 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC2 Loopback", "SPKDAT1R", "OUT5R" }, + { "SPKDAT1L", NULL, "OUT5L" }, + { "SPKDAT1R", NULL, "OUT5R" }, + + { "AEC1 Loopback", "SPKDAT2L", "OUT6L" }, + { "AEC1 Loopback", "SPKDAT2R", "OUT6R" }, + { "AEC2 Loopback", "SPKDAT2L", "OUT6L" }, + { "AEC2 Loopback", "SPKDAT2R", "OUT6R" }, + { "SPKDAT2L", NULL, "OUT6L" }, + { "SPKDAT2R", NULL, "OUT6R" }, + + CS47L85_RXANC_INPUT_ROUTES("RXANCL", "RXANCL"), + CS47L85_RXANC_INPUT_ROUTES("RXANCR", "RXANCR"), + + CS47L85_RXANC_OUTPUT_ROUTES("OUT1L", "HPOUT1L"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT1R", "HPOUT1R"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT2L", "HPOUT2L"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT2R", "HPOUT2R"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT3L", "HPOUT3L"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT3R", "HPOUT3R"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT4L", "SPKOUTL"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT4R", "SPKOUTR"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT5L", "SPKDAT1L"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT5R", "SPKDAT1R"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT6L", "SPKDAT2L"), + CS47L85_RXANC_OUTPUT_ROUTES("OUT6R", "SPKDAT2R"), + + { "SPDIF1", NULL, "SPD1" }, + + { "MICSUPP", NULL, "SYSCLK" }, + + { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" }, + { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" }, + { "DRC1 Activity Output", "Switch", "DRC1L" }, + { "DRC1 Activity Output", "Switch", "DRC1R" }, + { "DRC2 Activity Output", "Switch", "DRC2L" }, + { "DRC2 Activity Output", "Switch", "DRC2R" }, +}; + +static int cs47l85_set_fll(struct snd_soc_component *component, int fll_id, + int source, unsigned int fref, unsigned int fout) +{ + struct cs47l85 *cs47l85 = snd_soc_component_get_drvdata(component); + + switch (fll_id) { + case MADERA_FLL1_REFCLK: + return madera_set_fll_refclk(&cs47l85->fll[0], source, fref, + fout); + case MADERA_FLL2_REFCLK: + return madera_set_fll_refclk(&cs47l85->fll[1], source, fref, + fout); + case MADERA_FLL3_REFCLK: + return madera_set_fll_refclk(&cs47l85->fll[2], source, fref, + fout); + case MADERA_FLL1_SYNCCLK: + return madera_set_fll_syncclk(&cs47l85->fll[0], source, fref, + fout); + case MADERA_FLL2_SYNCCLK: + return madera_set_fll_syncclk(&cs47l85->fll[1], source, fref, + fout); + case MADERA_FLL3_SYNCCLK: + return madera_set_fll_syncclk(&cs47l85->fll[2], source, fref, + fout); + default: + return -EINVAL; + } +} + +static struct snd_soc_dai_driver cs47l85_dai[] = { + { + .name = "cs47l85-aif1", + .id = 1, + .base = MADERA_AIF1_BCLK_CTRL, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l85-aif2", + .id = 2, + .base = MADERA_AIF2_BCLK_CTRL, + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l85-aif3", + .id = 3, + .base = MADERA_AIF3_BCLK_CTRL, + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l85-aif4", + .id = 4, + .base = MADERA_AIF4_BCLK_CTRL, + .playback = { + .stream_name = "AIF4 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF4 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l85-slim1", + .id = 5, + .playback = { + .stream_name = "Slim1 Playback", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim1 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l85-slim2", + .id = 6, + .playback = { + .stream_name = "Slim2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l85-slim3", + .id = 7, + .playback = { + .stream_name = "Slim3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l85-cpu-voicectrl", + .capture = { + .stream_name = "Voice Control CPU", + .channels_min = 1, + .channels_max = 1, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .compress_new = &snd_soc_new_compress, + }, + { + .name = "cs47l85-dsp-voicectrl", + .capture = { + .stream_name = "Voice Control DSP", + .channels_min = 1, + .channels_max = 1, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + }, + { + .name = "cs47l85-cpu-trace", + .capture = { + .stream_name = "Audio Trace CPU", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .compress_new = &snd_soc_new_compress, + }, + { + .name = "cs47l85-dsp-trace", + .capture = { + .stream_name = "Audio Trace DSP", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + }, +}; + +static int cs47l85_open(struct snd_compr_stream *stream) +{ + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, DRV_NAME); + struct cs47l85 *cs47l85 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l85->core; + struct madera *madera = priv->madera; + int n_adsp; + + if (strcmp(rtd->codec_dai->name, "cs47l85-dsp-voicectrl") == 0) { + n_adsp = 5; + } else if (strcmp(rtd->codec_dai->name, "cs47l85-dsp-trace") == 0) { + n_adsp = 0; + } else { + dev_err(madera->dev, + "No suitable compressed stream for DAI '%s'\n", + rtd->codec_dai->name); + return -EINVAL; + } + + return wm_adsp_compr_open(&priv->adsp[n_adsp], stream); +} + +static irqreturn_t cs47l85_adsp2_irq(int irq, void *data) +{ + struct cs47l85 *cs47l85 = data; + struct madera_priv *priv = &cs47l85->core; + struct madera *madera = priv->madera; + struct madera_voice_trigger_info trig_info; + int serviced = 0; + int i, ret; + + for (i = 0; i < CS47L85_NUM_ADSP; ++i) { + ret = wm_adsp_compr_handle_irq(&priv->adsp[i]); + if (ret != -ENODEV) + serviced++; + if (ret == WM_ADSP_COMPR_VOICE_TRIGGER) { + trig_info.core_num = i + 1; + blocking_notifier_call_chain(&madera->notifier, + MADERA_NOTIFY_VOICE_TRIGGER, + &trig_info); + } + } + + if (!serviced) { + dev_err(madera->dev, "Spurious compressed data IRQ\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +static int cs47l85_component_probe(struct snd_soc_component *component) +{ + struct cs47l85 *cs47l85 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l85->core.madera; + int i, ret; + + snd_soc_component_init_regmap(component, madera->regmap); + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = snd_soc_component_get_dapm(component); + mutex_unlock(&madera->dapm_ptr_lock); + + ret = madera_init_inputs(component); + if (ret) + return ret; + + ret = madera_init_outputs(component, CS47L85_MONO_OUTPUTS); + if (ret) + return ret; + + snd_soc_component_disable_pin(component, "HAPTICS"); + + ret = snd_soc_add_component_controls(component, + madera_adsp_rate_controls, + CS47L85_NUM_ADSP); + if (ret) + return ret; + + for (i = 0; i < CS47L85_NUM_ADSP; i++) + wm_adsp2_component_probe(&cs47l85->core.adsp[i], component); + + return 0; +} + +static void cs47l85_component_remove(struct snd_soc_component *component) +{ + struct cs47l85 *cs47l85 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l85->core.madera; + int i; + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = NULL; + mutex_unlock(&madera->dapm_ptr_lock); + + for (i = 0; i < CS47L85_NUM_ADSP; i++) + wm_adsp2_component_remove(&cs47l85->core.adsp[i], component); +} + +#define MADERA_DIG_VU 0x0200 + +static const unsigned int cs47l85_digital_vu[] = { + MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, + MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, + MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, + MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_DAC_DIGITAL_VOLUME_4R, + MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, + MADERA_DAC_DIGITAL_VOLUME_6L, + MADERA_DAC_DIGITAL_VOLUME_6R, +}; + +static const struct snd_compr_ops cs47l85_compr_ops = { + .open = &cs47l85_open, + .free = &wm_adsp_compr_free, + .set_params = &wm_adsp_compr_set_params, + .get_caps = &wm_adsp_compr_get_caps, + .trigger = &wm_adsp_compr_trigger, + .pointer = &wm_adsp_compr_pointer, + .copy = &wm_adsp_compr_copy, +}; + +static const struct snd_soc_component_driver soc_component_dev_cs47l85 = { + .probe = &cs47l85_component_probe, + .remove = &cs47l85_component_remove, + .set_sysclk = &madera_set_sysclk, + .set_pll = &cs47l85_set_fll, + .name = DRV_NAME, + .compr_ops = &cs47l85_compr_ops, + .controls = cs47l85_snd_controls, + .num_controls = ARRAY_SIZE(cs47l85_snd_controls), + .dapm_widgets = cs47l85_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs47l85_dapm_widgets), + .dapm_routes = cs47l85_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs47l85_dapm_routes), + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static int cs47l85_probe(struct platform_device *pdev) +{ + struct madera *madera = dev_get_drvdata(pdev->dev.parent); + struct cs47l85 *cs47l85; + int i, ret; + + BUILD_BUG_ON(ARRAY_SIZE(cs47l85_dai) > MADERA_MAX_DAI); + + /* quick exit if Madera irqchip driver hasn't completed probe */ + if (!madera->irq_dev) { + dev_dbg(&pdev->dev, "irqchip driver not ready\n"); + return -EPROBE_DEFER; + } + + cs47l85 = devm_kzalloc(&pdev->dev, sizeof(struct cs47l85), + GFP_KERNEL); + if (!cs47l85) + return -ENOMEM; + + platform_set_drvdata(pdev, cs47l85); + + cs47l85->core.madera = madera; + cs47l85->core.dev = &pdev->dev; + cs47l85->core.num_inputs = 12; + + ret = madera_core_init(&cs47l85->core); + if (ret) + return ret; + + ret = madera_init_overheat(&cs47l85->core); + if (ret) + goto error_core; + + ret = madera_request_irq(madera, MADERA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", cs47l85_adsp2_irq, + cs47l85); + if (ret) { + dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); + goto error_overheat; + } + + ret = madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 1); + if (ret) + dev_warn(&pdev->dev, "Failed to set DSP IRQ wake: %d\n", ret); + + for (i = 0; i < CS47L85_NUM_ADSP; i++) { + cs47l85->core.adsp[i].part = "cs47l85"; + cs47l85->core.adsp[i].num = i + 1; + cs47l85->core.adsp[i].type = WMFW_ADSP2; + cs47l85->core.adsp[i].rev = 1; + cs47l85->core.adsp[i].dev = madera->dev; + cs47l85->core.adsp[i].regmap = madera->regmap_32bit; + + cs47l85->core.adsp[i].base = wm_adsp2_control_bases[i]; + cs47l85->core.adsp[i].mem = cs47l85_dsp_regions[i]; + cs47l85->core.adsp[i].num_mems = + ARRAY_SIZE(cs47l85_dsp1_regions); + + ret = wm_adsp2_init(&cs47l85->core.adsp[i]); + if (ret) { + for (--i; i >= 0; --i) + wm_adsp2_remove(&cs47l85->core.adsp[i]); + goto error_dsp_irq; + } + } + + madera_init_fll(madera, 1, MADERA_FLL1_CONTROL_1 - 1, + &cs47l85->fll[0]); + madera_init_fll(madera, 2, MADERA_FLL2_CONTROL_1 - 1, + &cs47l85->fll[1]); + madera_init_fll(madera, 3, MADERA_FLL3_CONTROL_1 - 1, + &cs47l85->fll[2]); + + for (i = 0; i < ARRAY_SIZE(cs47l85_dai); i++) + madera_init_dai(&cs47l85->core, i); + + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(cs47l85_digital_vu); i++) + regmap_update_bits(madera->regmap, cs47l85_digital_vu[i], + MADERA_DIG_VU, MADERA_DIG_VU); + + pm_runtime_enable(&pdev->dev); + pm_runtime_idle(&pdev->dev); + + ret = devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_cs47l85, + cs47l85_dai, + ARRAY_SIZE(cs47l85_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register component: %d\n", ret); + goto error_pm_runtime; + } + + return ret; + +error_pm_runtime: + pm_runtime_disable(&pdev->dev); + + for (i = 0; i < CS47L85_NUM_ADSP; i++) + wm_adsp2_remove(&cs47l85->core.adsp[i]); +error_dsp_irq: + madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(madera, MADERA_IRQ_DSP_IRQ1, cs47l85); +error_overheat: + madera_free_overheat(&cs47l85->core); +error_core: + madera_core_free(&cs47l85->core); + + return ret; +} + +static int cs47l85_remove(struct platform_device *pdev) +{ + struct cs47l85 *cs47l85 = platform_get_drvdata(pdev); + int i; + + pm_runtime_disable(&pdev->dev); + + for (i = 0; i < CS47L85_NUM_ADSP; i++) + wm_adsp2_remove(&cs47l85->core.adsp[i]); + + madera_set_irq_wake(cs47l85->core.madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(cs47l85->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l85); + madera_free_overheat(&cs47l85->core); + madera_core_free(&cs47l85->core); + + return 0; +} + +static struct platform_driver cs47l85_codec_driver = { + .driver = { + .name = "cs47l85-codec", + }, + .probe = &cs47l85_probe, + .remove = &cs47l85_remove, +}; + +module_platform_driver(cs47l85_codec_driver); + +MODULE_SOFTDEP("pre: madera irq-madera arizona-micsupp"); +MODULE_DESCRIPTION("ASoC CS47L85 driver"); +MODULE_AUTHOR("Nariman Poushin "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:cs47l85-codec"); From f1572a4489543c051a6097a706b91ff0f1c2175d Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 19 Jun 2019 14:41:59 +0100 Subject: [PATCH 479/626] ASoC: cs47l90: Add codec driver for Cirrus Logic CS47L90 Adds the codec driver for the CS47L90 SmartCodec. This is a multi-functional codec based on the Cirrus Logic Madera platform. Signed-off-by: Nikesh Oswal Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/cs47l90.c | 2657 ++++++++++++++++++++++++++++++++++++ 3 files changed, 2665 insertions(+) create mode 100644 sound/soc/codecs/cs47l90.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a8aa801b9342..ff88f0b7d61d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -72,6 +72,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS47L24 if MFD_CS47L24 select SND_SOC_CS47L35 if MFD_CS47L35 select SND_SOC_CS47L85 if MFD_CS47L85 + select SND_SOC_CS47L90 if MFD_CS47L90 select SND_SOC_CS53L30 if I2C select SND_SOC_CX20442 if TTY select SND_SOC_CX2072X if I2C @@ -587,6 +588,9 @@ config SND_SOC_CS47L35 config SND_SOC_CS47L85 tristate +config SND_SOC_CS47L90 + tristate + # Cirrus Logic Quad-Channel ADC config SND_SOC_CS53L30 tristate "Cirrus Logic CS53L30 CODEC" @@ -718,8 +722,10 @@ config SND_SOC_MADERA tristate default y if SND_SOC_CS47L35=y default y if SND_SOC_CS47L85=y + default y if SND_SOC_CS47L90=y default m if SND_SOC_CS47L35=m default m if SND_SOC_CS47L85=m + default m if SND_SOC_CS47L90=m config SND_SOC_MAX98088 tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index ce02d1fb250b..ed74f5babf59 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -67,6 +67,7 @@ snd-soc-cs4349-objs := cs4349.o snd-soc-cs47l24-objs := cs47l24.o snd-soc-cs47l35-objs := cs47l35.o snd-soc-cs47l85-objs := cs47l85.o +snd-soc-cs47l90-objs := cs47l90.o snd-soc-cs53l30-objs := cs53l30.o snd-soc-cx20442-objs := cx20442.o snd-soc-cx2072x-objs := cx2072x.o @@ -346,6 +347,7 @@ obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o +obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c new file mode 100644 index 000000000000..83c4e4628bde --- /dev/null +++ b/sound/soc/codecs/cs47l90.c @@ -0,0 +1,2657 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// ALSA SoC Audio driver for CS47L90 codec +// +// Copyright (C) 2015-2019 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by the +// Free Software Foundation; version 2. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "madera.h" +#include "wm_adsp.h" + +#define DRV_NAME "cs47l90-codec" + +#define CS47L90_NUM_ADSP 7 +#define CS47L90_MONO_OUTPUTS 3 + +struct cs47l90 { + struct madera_priv core; + struct madera_fll fll[3]; +}; + +static const struct wm_adsp_region cs47l90_dsp1_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x080000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x0e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x0a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x0c0000 }, +}; + +static const struct wm_adsp_region cs47l90_dsp2_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x100000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x160000 }, + { .type = WMFW_ADSP2_XM, .base = 0x120000 }, + { .type = WMFW_ADSP2_YM, .base = 0x140000 }, +}; + +static const struct wm_adsp_region cs47l90_dsp3_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x180000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x1e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x1a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x1c0000 }, +}; + +static const struct wm_adsp_region cs47l90_dsp4_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x200000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x260000 }, + { .type = WMFW_ADSP2_XM, .base = 0x220000 }, + { .type = WMFW_ADSP2_YM, .base = 0x240000 }, +}; + +static const struct wm_adsp_region cs47l90_dsp5_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x280000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x2e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x2a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x2c0000 }, +}; + +static const struct wm_adsp_region cs47l90_dsp6_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x300000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x360000 }, + { .type = WMFW_ADSP2_XM, .base = 0x320000 }, + { .type = WMFW_ADSP2_YM, .base = 0x340000 }, +}; + +static const struct wm_adsp_region cs47l90_dsp7_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x380000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x3e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x3a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x3c0000 }, +}; + +static const struct wm_adsp_region *cs47l90_dsp_regions[] = { + cs47l90_dsp1_regions, + cs47l90_dsp2_regions, + cs47l90_dsp3_regions, + cs47l90_dsp4_regions, + cs47l90_dsp5_regions, + cs47l90_dsp6_regions, + cs47l90_dsp7_regions, +}; + +static const int cs47l90_dsp_control_bases[] = { + MADERA_DSP1_CONFIG_1, + MADERA_DSP2_CONFIG_1, + MADERA_DSP3_CONFIG_1, + MADERA_DSP4_CONFIG_1, + MADERA_DSP5_CONFIG_1, + MADERA_DSP6_CONFIG_1, + MADERA_DSP7_CONFIG_1, +}; + +static int cs47l90_adsp_power_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l90->core; + struct madera *madera = priv->madera; + unsigned int freq; + int ret; + + ret = regmap_read(madera->regmap, MADERA_DSP_CLOCK_2, &freq); + if (ret != 0) { + dev_err(madera->dev, + "Failed to read MADERA_DSP_CLOCK_2: %d\n", ret); + return ret; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = madera_set_adsp_clk(&cs47l90->core, w->shift, freq); + if (ret) + return ret; + break; + default: + break; + } + + return wm_adsp_early_event(w, kcontrol, event); +} + +#define CS47L90_NG_SRC(name, base) \ + SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ + SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ + SOC_SINGLE(name " NG HPOUT2L Switch", base, 2, 1, 0), \ + SOC_SINGLE(name " NG HPOUT2R Switch", base, 3, 1, 0), \ + SOC_SINGLE(name " NG HPOUT3L Switch", base, 4, 1, 0), \ + SOC_SINGLE(name " NG HPOUT3R Switch", base, 5, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0) + +#define CS47L90_RXANC_INPUT_ROUTES(widget, name) \ + { widget, NULL, name " NG Mux" }, \ + { name " NG Internal", NULL, "RXANC NG Clock" }, \ + { name " NG Internal", NULL, name " Channel" }, \ + { name " NG External", NULL, "RXANC NG External Clock" }, \ + { name " NG External", NULL, name " Channel" }, \ + { name " NG Mux", "None", name " Channel" }, \ + { name " NG Mux", "Internal", name " NG Internal" }, \ + { name " NG Mux", "External", name " NG External" }, \ + { name " Channel", "Left", name " Left Input" }, \ + { name " Channel", "Combine", name " Left Input" }, \ + { name " Channel", "Right", name " Right Input" }, \ + { name " Channel", "Combine", name " Right Input" }, \ + { name " Left Input", "IN1", "IN1L" }, \ + { name " Right Input", "IN1", "IN1R" }, \ + { name " Left Input", "IN2", "IN2L" }, \ + { name " Right Input", "IN2", "IN2R" }, \ + { name " Left Input", "IN3", "IN3L" }, \ + { name " Right Input", "IN3", "IN3R" }, \ + { name " Left Input", "IN4", "IN4L" }, \ + { name " Right Input", "IN4", "IN4R" }, \ + { name " Left Input", "IN5", "IN5L" }, \ + { name " Right Input", "IN5", "IN5R" } + +#define CS47L90_RXANC_OUTPUT_ROUTES(widget, name) \ + { widget, NULL, name " ANC Source" }, \ + { name " ANC Source", "RXANCL", "RXANCL" }, \ + { name " ANC Source", "RXANCR", "RXANCR" } + +static const struct snd_kcontrol_new cs47l90_snd_controls[] = { +SOC_ENUM("IN1 OSR", madera_in_dmic_osr[0]), +SOC_ENUM("IN2 OSR", madera_in_dmic_osr[1]), +SOC_ENUM("IN3 OSR", madera_in_dmic_osr[2]), +SOC_ENUM("IN4 OSR", madera_in_dmic_osr[3]), +SOC_ENUM("IN5 OSR", madera_in_dmic_osr[4]), + +SOC_SINGLE_RANGE_TLV("IN1L Volume", MADERA_IN1L_CONTROL, + MADERA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN1R Volume", MADERA_IN1R_CONTROL, + MADERA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2L Volume", MADERA_IN2L_CONTROL, + MADERA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2R Volume", MADERA_IN2R_CONTROL, + MADERA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), + +SOC_ENUM("IN HPF Cutoff Frequency", madera_in_hpf_cut_enum), + +SOC_SINGLE_EXT("IN1L LP Switch", MADERA_ADC_DIGITAL_VOLUME_1L, + MADERA_IN1L_LP_MODE_SHIFT, 1, 0, + snd_soc_get_volsw, madera_lp_mode_put), +SOC_SINGLE_EXT("IN1R LP Switch", MADERA_ADC_DIGITAL_VOLUME_1R, + MADERA_IN1R_LP_MODE_SHIFT, 1, 0, + snd_soc_get_volsw, madera_lp_mode_put), +SOC_SINGLE_EXT("IN2L LP Switch", MADERA_ADC_DIGITAL_VOLUME_2L, + MADERA_IN2L_LP_MODE_SHIFT, 1, 0, + snd_soc_get_volsw, madera_lp_mode_put), +SOC_SINGLE_EXT("IN2R LP Switch", MADERA_ADC_DIGITAL_VOLUME_2R, + MADERA_IN2R_LP_MODE_SHIFT, 1, 0, + snd_soc_get_volsw, madera_lp_mode_put), + +SOC_SINGLE("IN1L HPF Switch", MADERA_IN1L_CONTROL, + MADERA_IN1L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN1R HPF Switch", MADERA_IN1R_CONTROL, + MADERA_IN1R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2L HPF Switch", MADERA_IN2L_CONTROL, + MADERA_IN2L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2R HPF Switch", MADERA_IN2R_CONTROL, + MADERA_IN2R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN3L HPF Switch", MADERA_IN3L_CONTROL, + MADERA_IN3L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN3R HPF Switch", MADERA_IN3R_CONTROL, + MADERA_IN3R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN4L HPF Switch", MADERA_IN4L_CONTROL, + MADERA_IN4L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN4R HPF Switch", MADERA_IN4R_CONTROL, + MADERA_IN4R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN5L HPF Switch", MADERA_IN5L_CONTROL, + MADERA_IN5L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN5R HPF Switch", MADERA_IN5R_CONTROL, + MADERA_IN5R_HPF_SHIFT, 1, 0), + +SOC_SINGLE_TLV("IN1L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1L, + MADERA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN1R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1R, + MADERA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2L, + MADERA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2R, + MADERA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN3L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_3L, + MADERA_IN3L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN3R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_3R, + MADERA_IN3R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN4L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_4L, + MADERA_IN4L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN4R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_4R, + MADERA_IN4R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN5L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_5L, + MADERA_IN5L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN5R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_5R, + MADERA_IN5R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), + +SOC_ENUM("Input Ramp Up", madera_in_vi_ramp), +SOC_ENUM("Input Ramp Down", madera_in_vd_ramp), + +SND_SOC_BYTES("RXANC Coefficients", MADERA_ANC_COEFF_START, + MADERA_ANC_COEFF_END - MADERA_ANC_COEFF_START + 1), +SND_SOC_BYTES("RXANCL Config", MADERA_FCL_FILTER_CONTROL, 1), +SND_SOC_BYTES("RXANCL Coefficients", MADERA_FCL_COEFF_START, + MADERA_FCL_COEFF_END - MADERA_FCL_COEFF_START + 1), +SND_SOC_BYTES("RXANCR Config", MADERA_FCR_FILTER_CONTROL, 1), +SND_SOC_BYTES("RXANCR Coefficients", MADERA_FCR_COEFF_START, + MADERA_FCR_COEFF_END - MADERA_FCR_COEFF_START + 1), + +MADERA_MIXER_CONTROLS("EQ1", MADERA_EQ1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ2", MADERA_EQ2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ3", MADERA_EQ3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ4", MADERA_EQ4MIX_INPUT_1_SOURCE), + +MADERA_EQ_CONTROL("EQ1 Coefficients", MADERA_EQ1_2), +SOC_SINGLE_TLV("EQ1 B1 Volume", MADERA_EQ1_1, MADERA_EQ1_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B2 Volume", MADERA_EQ1_1, MADERA_EQ1_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B3 Volume", MADERA_EQ1_1, MADERA_EQ1_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B4 Volume", MADERA_EQ1_2, MADERA_EQ1_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B5 Volume", MADERA_EQ1_2, MADERA_EQ1_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ2 Coefficients", MADERA_EQ2_2), +SOC_SINGLE_TLV("EQ2 B1 Volume", MADERA_EQ2_1, MADERA_EQ2_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B2 Volume", MADERA_EQ2_1, MADERA_EQ2_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B3 Volume", MADERA_EQ2_1, MADERA_EQ2_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B4 Volume", MADERA_EQ2_2, MADERA_EQ2_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B5 Volume", MADERA_EQ2_2, MADERA_EQ2_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ3 Coefficients", MADERA_EQ3_2), +SOC_SINGLE_TLV("EQ3 B1 Volume", MADERA_EQ3_1, MADERA_EQ3_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B2 Volume", MADERA_EQ3_1, MADERA_EQ3_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B3 Volume", MADERA_EQ3_1, MADERA_EQ3_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B4 Volume", MADERA_EQ3_2, MADERA_EQ3_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B5 Volume", MADERA_EQ3_2, MADERA_EQ3_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ4 Coefficients", MADERA_EQ4_2), +SOC_SINGLE_TLV("EQ4 B1 Volume", MADERA_EQ4_1, MADERA_EQ4_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B2 Volume", MADERA_EQ4_1, MADERA_EQ4_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B3 Volume", MADERA_EQ4_1, MADERA_EQ4_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B4 Volume", MADERA_EQ4_2, MADERA_EQ4_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B5 Volume", MADERA_EQ4_2, MADERA_EQ4_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_MIXER_CONTROLS("DRC1L", MADERA_DRC1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC1R", MADERA_DRC1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2L", MADERA_DRC2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2R", MADERA_DRC2RMIX_INPUT_1_SOURCE), + +SND_SOC_BYTES_MASK("DRC1", MADERA_DRC1_CTRL1, 5, + MADERA_DRC1R_ENA | MADERA_DRC1L_ENA), +SND_SOC_BYTES_MASK("DRC2", MADERA_DRC2_CTRL1, 5, + MADERA_DRC2R_ENA | MADERA_DRC2L_ENA), + +MADERA_MIXER_CONTROLS("LHPF1", MADERA_HPLP1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF2", MADERA_HPLP2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF3", MADERA_HPLP3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF4", MADERA_HPLP4MIX_INPUT_1_SOURCE), + +MADERA_LHPF_CONTROL("LHPF1 Coefficients", MADERA_HPLPF1_2), +MADERA_LHPF_CONTROL("LHPF2 Coefficients", MADERA_HPLPF2_2), +MADERA_LHPF_CONTROL("LHPF3 Coefficients", MADERA_HPLPF3_2), +MADERA_LHPF_CONTROL("LHPF4 Coefficients", MADERA_HPLPF4_2), + +SOC_ENUM("LHPF1 Mode", madera_lhpf1_mode), +SOC_ENUM("LHPF2 Mode", madera_lhpf2_mode), +SOC_ENUM("LHPF3 Mode", madera_lhpf3_mode), +SOC_ENUM("LHPF4 Mode", madera_lhpf4_mode), + +MADERA_RATE_ENUM("ISRC1 FSL", madera_isrc_fsl[0]), +MADERA_RATE_ENUM("ISRC2 FSL", madera_isrc_fsl[1]), +MADERA_RATE_ENUM("ISRC3 FSL", madera_isrc_fsl[2]), +MADERA_RATE_ENUM("ISRC4 FSL", madera_isrc_fsl[3]), +MADERA_RATE_ENUM("ISRC1 FSH", madera_isrc_fsh[0]), +MADERA_RATE_ENUM("ISRC2 FSH", madera_isrc_fsh[1]), +MADERA_RATE_ENUM("ISRC3 FSH", madera_isrc_fsh[2]), +MADERA_RATE_ENUM("ISRC4 FSH", madera_isrc_fsh[3]), +MADERA_RATE_ENUM("ASRC1 Rate 1", madera_asrc1_rate[0]), +MADERA_RATE_ENUM("ASRC1 Rate 2", madera_asrc1_rate[1]), +MADERA_RATE_ENUM("ASRC2 Rate 1", madera_asrc2_rate[0]), +MADERA_RATE_ENUM("ASRC2 Rate 2", madera_asrc2_rate[1]), + +WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), +WM_ADSP2_PRELOAD_SWITCH("DSP2", 2), +WM_ADSP2_PRELOAD_SWITCH("DSP3", 3), +WM_ADSP2_PRELOAD_SWITCH("DSP4", 4), +WM_ADSP2_PRELOAD_SWITCH("DSP5", 5), +WM_ADSP2_PRELOAD_SWITCH("DSP6", 6), +WM_ADSP2_PRELOAD_SWITCH("DSP7", 7), + +MADERA_MIXER_CONTROLS("DSP1L", MADERA_DSP1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP1R", MADERA_DSP1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP2L", MADERA_DSP2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP2R", MADERA_DSP2RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP3L", MADERA_DSP3LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP3R", MADERA_DSP3RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP4L", MADERA_DSP4LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP4R", MADERA_DSP4RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP5L", MADERA_DSP5LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP5R", MADERA_DSP5RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP6L", MADERA_DSP6LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP6R", MADERA_DSP6RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP7L", MADERA_DSP7LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP7R", MADERA_DSP7RMIX_INPUT_1_SOURCE), + +SOC_SINGLE_TLV("Noise Generator Volume", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, madera_noise_tlv), + +MADERA_MIXER_CONTROLS("HPOUT1L", MADERA_OUT1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT1R", MADERA_OUT1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT2L", MADERA_OUT2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT2R", MADERA_OUT2RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT3L", MADERA_OUT3LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT3R", MADERA_OUT3RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1L", MADERA_OUT5LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1R", MADERA_OUT5RMIX_INPUT_1_SOURCE), + +SOC_SINGLE("HPOUT1 SC Protect Switch", MADERA_HP1_SHORT_CIRCUIT_CTRL, + MADERA_HP1_SC_ENA_SHIFT, 1, 0), +SOC_SINGLE("HPOUT2 SC Protect Switch", MADERA_HP2_SHORT_CIRCUIT_CTRL, + MADERA_HP2_SC_ENA_SHIFT, 1, 0), +SOC_SINGLE("HPOUT3 SC Protect Switch", MADERA_HP3_SHORT_CIRCUIT_CTRL, + MADERA_HP3_SC_ENA_SHIFT, 1, 0), + +SOC_SINGLE("SPKDAT1 High Performance Switch", MADERA_OUTPUT_PATH_CONFIG_5L, + MADERA_OUT5_OSR_SHIFT, 1, 0), + +SOC_DOUBLE_R("HPOUT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("HPOUT2 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, MADERA_OUT2L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("HPOUT3 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, MADERA_OUT3L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_MUTE_SHIFT, 1, 1), + +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, MADERA_OUT2L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, MADERA_OUT3L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), + +SOC_DOUBLE("SPKDAT1 Switch", MADERA_PDM_SPK1_CTRL_1, MADERA_SPK1L_MUTE_SHIFT, + MADERA_SPK1R_MUTE_SHIFT, 1, 1), + +SOC_ENUM("Output Ramp Up", madera_out_vi_ramp), +SOC_ENUM("Output Ramp Down", madera_out_vd_ramp), + +SOC_SINGLE("Noise Gate Switch", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_ENA_SHIFT, 1, 0), +SOC_SINGLE_TLV("Noise Gate Threshold Volume", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_THR_SHIFT, 7, 1, madera_ng_tlv), +SOC_ENUM("Noise Gate Hold", madera_ng_hold), + +SOC_ENUM_EXT("DFC1RX Width", madera_dfc_width[0], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC1RX Type", madera_dfc_type[0], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC1TX Width", madera_dfc_width[1], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC1TX Type", madera_dfc_type[1], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC2RX Width", madera_dfc_width[2], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC2RX Type", madera_dfc_type[2], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC2TX Width", madera_dfc_width[3], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC2TX Type", madera_dfc_type[3], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC3RX Width", madera_dfc_width[4], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC3RX Type", madera_dfc_type[4], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC3TX Width", madera_dfc_width[5], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC3TX Type", madera_dfc_type[5], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC4RX Width", madera_dfc_width[6], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC4RX Type", madera_dfc_type[6], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC4TX Width", madera_dfc_width[7], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC4TX Type", madera_dfc_type[7], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC5RX Width", madera_dfc_width[8], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC5RX Type", madera_dfc_type[8], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC5TX Width", madera_dfc_width[9], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC5TX Type", madera_dfc_type[9], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC6RX Width", madera_dfc_width[10], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC6RX Type", madera_dfc_type[10], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC6TX Width", madera_dfc_width[11], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC6TX Type", madera_dfc_type[11], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC7RX Width", madera_dfc_width[12], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC7RX Type", madera_dfc_type[12], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC7TX Width", madera_dfc_width[13], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC7TX Type", madera_dfc_type[13], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC8RX Width", madera_dfc_width[14], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC8RX Type", madera_dfc_type[14], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC8TX Width", madera_dfc_width[15], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC8TX Type", madera_dfc_type[15], + snd_soc_get_enum_double, madera_dfc_put), + +CS47L90_NG_SRC("HPOUT1L", MADERA_NOISE_GATE_SELECT_1L), +CS47L90_NG_SRC("HPOUT1R", MADERA_NOISE_GATE_SELECT_1R), +CS47L90_NG_SRC("HPOUT2L", MADERA_NOISE_GATE_SELECT_2L), +CS47L90_NG_SRC("HPOUT2R", MADERA_NOISE_GATE_SELECT_2R), +CS47L90_NG_SRC("HPOUT3L", MADERA_NOISE_GATE_SELECT_3L), +CS47L90_NG_SRC("HPOUT3R", MADERA_NOISE_GATE_SELECT_3R), +CS47L90_NG_SRC("SPKDAT1L", MADERA_NOISE_GATE_SELECT_5L), +CS47L90_NG_SRC("SPKDAT1R", MADERA_NOISE_GATE_SELECT_5R), + +MADERA_MIXER_CONTROLS("AIF1TX1", MADERA_AIF1TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX2", MADERA_AIF1TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX3", MADERA_AIF1TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX4", MADERA_AIF1TX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX5", MADERA_AIF1TX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX6", MADERA_AIF1TX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX7", MADERA_AIF1TX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX8", MADERA_AIF1TX8MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF2TX1", MADERA_AIF2TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX2", MADERA_AIF2TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX3", MADERA_AIF2TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX4", MADERA_AIF2TX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX5", MADERA_AIF2TX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX6", MADERA_AIF2TX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX7", MADERA_AIF2TX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX8", MADERA_AIF2TX8MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF3TX1", MADERA_AIF3TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF3TX2", MADERA_AIF3TX2MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF4TX1", MADERA_AIF4TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF4TX2", MADERA_AIF4TX2MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("SLIMTX1", MADERA_SLIMTX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX2", MADERA_SLIMTX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX3", MADERA_SLIMTX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX4", MADERA_SLIMTX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX5", MADERA_SLIMTX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX6", MADERA_SLIMTX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX7", MADERA_SLIMTX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX8", MADERA_SLIMTX8MIX_INPUT_1_SOURCE), + +MADERA_GAINMUX_CONTROLS("SPDIF1TX1", MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE), +MADERA_GAINMUX_CONTROLS("SPDIF1TX2", MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP1", 0), +WM_ADSP_FW_CONTROL("DSP2", 1), +WM_ADSP_FW_CONTROL("DSP3", 2), +WM_ADSP_FW_CONTROL("DSP4", 3), +WM_ADSP_FW_CONTROL("DSP5", 4), +WM_ADSP_FW_CONTROL("DSP6", 5), +WM_ADSP_FW_CONTROL("DSP7", 6), +}; + +MADERA_MIXER_ENUMS(EQ1, MADERA_EQ1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ2, MADERA_EQ2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ3, MADERA_EQ3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ4, MADERA_EQ4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DRC1L, MADERA_DRC1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC1R, MADERA_DRC1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2L, MADERA_DRC2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2R, MADERA_DRC2RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(LHPF1, MADERA_HPLP1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF2, MADERA_HPLP2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF3, MADERA_HPLP3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF4, MADERA_HPLP4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP1L, MADERA_DSP1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP1R, MADERA_DSP1RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP1, MADERA_DSP1AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP2L, MADERA_DSP2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP2R, MADERA_DSP2RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP2, MADERA_DSP2AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP3L, MADERA_DSP3LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP3R, MADERA_DSP3RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP3, MADERA_DSP3AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP4L, MADERA_DSP4LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP4R, MADERA_DSP4RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP4, MADERA_DSP4AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP5L, MADERA_DSP5LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP5R, MADERA_DSP5RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP5, MADERA_DSP5AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP6L, MADERA_DSP6LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP6R, MADERA_DSP6RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP6, MADERA_DSP6AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP7L, MADERA_DSP7LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP7R, MADERA_DSP7RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP7, MADERA_DSP7AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(PWM1, MADERA_PWM1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(PWM2, MADERA_PWM2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(OUT1L, MADERA_OUT1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT1R, MADERA_OUT1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT2L, MADERA_OUT2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT2R, MADERA_OUT2RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT3L, MADERA_OUT3LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT3R, MADERA_OUT3RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1L, MADERA_OUT5LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1R, MADERA_OUT5RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF1TX1, MADERA_AIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX2, MADERA_AIF1TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX3, MADERA_AIF1TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX4, MADERA_AIF1TX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX5, MADERA_AIF1TX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX6, MADERA_AIF1TX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX7, MADERA_AIF1TX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX8, MADERA_AIF1TX8MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF2TX1, MADERA_AIF2TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX2, MADERA_AIF2TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX3, MADERA_AIF2TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX4, MADERA_AIF2TX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX5, MADERA_AIF2TX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX6, MADERA_AIF2TX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX7, MADERA_AIF2TX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX8, MADERA_AIF2TX8MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF3TX1, MADERA_AIF3TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF3TX2, MADERA_AIF3TX2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF4TX1, MADERA_AIF4TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF4TX2, MADERA_AIF4TX2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(SLIMTX1, MADERA_SLIMTX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX2, MADERA_SLIMTX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX3, MADERA_SLIMTX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX4, MADERA_SLIMTX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX5, MADERA_SLIMTX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX6, MADERA_SLIMTX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX7, MADERA_SLIMTX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX8, MADERA_SLIMTX8MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(SPD1TX1, MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(SPD1TX2, MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ASRC1IN1L, MADERA_ASRC1_1LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN1R, MADERA_ASRC1_1RMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN2L, MADERA_ASRC1_2LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN2R, MADERA_ASRC1_2RMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC2IN1L, MADERA_ASRC2_1LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC2IN1R, MADERA_ASRC2_1RMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC2IN2L, MADERA_ASRC2_2LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC2IN2R, MADERA_ASRC2_2RMIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1INT1, MADERA_ISRC1INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT2, MADERA_ISRC1INT2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT3, MADERA_ISRC1INT3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT4, MADERA_ISRC1INT4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1DEC1, MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC2, MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC3, MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC4, MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2INT1, MADERA_ISRC2INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT2, MADERA_ISRC2INT2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT3, MADERA_ISRC2INT3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT4, MADERA_ISRC2INT4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2DEC1, MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC2, MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC3, MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC4, MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC3INT1, MADERA_ISRC3INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC3INT2, MADERA_ISRC3INT2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC3DEC1, MADERA_ISRC3DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC3DEC2, MADERA_ISRC3DEC2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC4INT1, MADERA_ISRC4INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC4INT2, MADERA_ISRC4INT2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC4DEC1, MADERA_ISRC4DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC4DEC2, MADERA_ISRC4DEC2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(DFC1, MADERA_DFC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC2, MADERA_DFC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC3, MADERA_DFC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC4, MADERA_DFC4MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC5, MADERA_DFC5MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC6, MADERA_DFC6MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC7, MADERA_DFC7MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC8, MADERA_DFC8MIX_INPUT_1_SOURCE); + +static const char * const cs47l90_aec_loopback_texts[] = { + "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", + "SPKDAT1L", "SPKDAT1R", +}; + +static const unsigned int cs47l90_aec_loopback_values[] = { + 0, 1, 2, 3, 4, 5, 8, 9, +}; + +static const struct soc_enum cs47l90_aec1_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l90_aec_loopback_texts), + cs47l90_aec_loopback_texts, + cs47l90_aec_loopback_values); + +static const struct soc_enum cs47l90_aec2_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_2, + MADERA_AEC2_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l90_aec_loopback_texts), + cs47l90_aec_loopback_texts, + cs47l90_aec_loopback_values); + +static const struct snd_kcontrol_new cs47l90_aec_loopback_mux[] = { + SOC_DAPM_ENUM("AEC1 Loopback", cs47l90_aec1_loopback), + SOC_DAPM_ENUM("AEC2 Loopback", cs47l90_aec2_loopback), +}; + +static const struct snd_kcontrol_new cs47l90_anc_input_mux[] = { + SOC_DAPM_ENUM("RXANCL Input", madera_anc_input_src[0]), + SOC_DAPM_ENUM("RXANCL Channel", madera_anc_input_src[1]), + SOC_DAPM_ENUM("RXANCR Input", madera_anc_input_src[2]), + SOC_DAPM_ENUM("RXANCR Channel", madera_anc_input_src[3]), +}; + +static const struct snd_kcontrol_new cs47l90_anc_ng_mux = + SOC_DAPM_ENUM("RXANC NG Source", madera_anc_ng_enum); + +static const struct snd_kcontrol_new cs47l90_output_anc_src[] = { + SOC_DAPM_ENUM("HPOUT1L ANC Source", madera_output_anc_src[0]), + SOC_DAPM_ENUM("HPOUT1R ANC Source", madera_output_anc_src[1]), + SOC_DAPM_ENUM("HPOUT2L ANC Source", madera_output_anc_src[2]), + SOC_DAPM_ENUM("HPOUT2R ANC Source", madera_output_anc_src[3]), + SOC_DAPM_ENUM("HPOUT3L ANC Source", madera_output_anc_src[4]), + SOC_DAPM_ENUM("HPOUT3R ANC Source", madera_output_anc_src[0]), + SOC_DAPM_ENUM("SPKDAT1L ANC Source", madera_output_anc_src[8]), + SOC_DAPM_ENUM("SPKDAT1R ANC Source", madera_output_anc_src[9]), +}; + +static const struct snd_soc_dapm_widget cs47l90_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, + 0, madera_sysclk_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, + MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, + MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, + MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, + MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD4", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD2", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), + +SND_SOC_DAPM_SUPPLY("MICBIAS1", MADERA_MIC_BIAS_CTRL_1, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", MADERA_MIC_BIAS_CTRL_2, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS1A", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1A_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1B", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1B_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1C", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1C_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1D", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1D_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS2A", MADERA_MIC_BIAS_CTRL_6, + MADERA_MICB2A_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2B", MADERA_MIC_BIAS_CTRL_6, + MADERA_MICB2B_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2C", MADERA_MIC_BIAS_CTRL_6, + MADERA_MICB2C_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2D", MADERA_MIC_BIAS_CTRL_6, + MADERA_MICB2D_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("FXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_FX, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ASRC1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ASRC1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ASRC2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ASRC2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC3CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC4CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC4, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_OUT, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SPD, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP3CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP4CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP4, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP5CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP5, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP6CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP6, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP7CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP7, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF1TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF2TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF3TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF4TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF4, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SLIMBUSCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SLIMBUS, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("PWMCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_PWM, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DFCCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DFC, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + +SND_SOC_DAPM_SIGGEN("TONE"), +SND_SOC_DAPM_SIGGEN("NOISE"), + +SND_SOC_DAPM_INPUT("IN1ALN"), +SND_SOC_DAPM_INPUT("IN1ALP"), +SND_SOC_DAPM_INPUT("IN1BLN"), +SND_SOC_DAPM_INPUT("IN1BLP"), +SND_SOC_DAPM_INPUT("IN1ARN"), +SND_SOC_DAPM_INPUT("IN1ARP"), +SND_SOC_DAPM_INPUT("IN1BRN"), +SND_SOC_DAPM_INPUT("IN1BRP"), +SND_SOC_DAPM_INPUT("IN2ALN"), +SND_SOC_DAPM_INPUT("IN2ALP"), +SND_SOC_DAPM_INPUT("IN2BLN"), +SND_SOC_DAPM_INPUT("IN2BLP"), +SND_SOC_DAPM_INPUT("IN2RN"), +SND_SOC_DAPM_INPUT("IN2RP"), +SND_SOC_DAPM_INPUT("DMICCLK3"), +SND_SOC_DAPM_INPUT("DMICDAT3"), +SND_SOC_DAPM_INPUT("DMICCLK4"), +SND_SOC_DAPM_INPUT("DMICDAT4"), +SND_SOC_DAPM_INPUT("DMICCLK5"), +SND_SOC_DAPM_INPUT("DMICDAT5"), + +SND_SOC_DAPM_MUX("IN1L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[0]), +SND_SOC_DAPM_MUX("IN1R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[1]), +SND_SOC_DAPM_MUX("IN2L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[2]), + +SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), +SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), + +SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), +SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), + +SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), +SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), + +SND_SOC_DAPM_OUTPUT("DSP Trigger Out"), + +SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("RXANC NG External Clock", SND_SOC_NOPM, + MADERA_EXT_NG_SEL_SET_SHIFT, 0, madera_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA("RXANCL NG External", SND_SOC_NOPM, 0, 0, NULL, 0), +SND_SOC_DAPM_PGA("RXANCR NG External", SND_SOC_NOPM, 0, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("RXANC NG Clock", SND_SOC_NOPM, + MADERA_CLK_NG_ENA_SET_SHIFT, 0, madera_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA("RXANCL NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0), +SND_SOC_DAPM_PGA("RXANCR NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0), + +SND_SOC_DAPM_MUX("RXANCL Left Input", SND_SOC_NOPM, 0, 0, + &cs47l90_anc_input_mux[0]), +SND_SOC_DAPM_MUX("RXANCL Right Input", SND_SOC_NOPM, 0, 0, + &cs47l90_anc_input_mux[0]), +SND_SOC_DAPM_MUX("RXANCL Channel", SND_SOC_NOPM, 0, 0, + &cs47l90_anc_input_mux[1]), +SND_SOC_DAPM_MUX("RXANCL NG Mux", SND_SOC_NOPM, 0, 0, &cs47l90_anc_ng_mux), +SND_SOC_DAPM_MUX("RXANCR Left Input", SND_SOC_NOPM, 0, 0, + &cs47l90_anc_input_mux[2]), +SND_SOC_DAPM_MUX("RXANCR Right Input", SND_SOC_NOPM, 0, 0, + &cs47l90_anc_input_mux[2]), +SND_SOC_DAPM_MUX("RXANCR Channel", SND_SOC_NOPM, 0, 0, + &cs47l90_anc_input_mux[3]), +SND_SOC_DAPM_MUX("RXANCR NG Mux", SND_SOC_NOPM, 0, 0, &cs47l90_anc_ng_mux), + +SND_SOC_DAPM_PGA_E("RXANCL", SND_SOC_NOPM, MADERA_CLK_L_ENA_SET_SHIFT, + 0, NULL, 0, madera_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA_E("RXANCR", SND_SOC_NOPM, MADERA_CLK_R_ENA_SET_SHIFT, + 0, NULL, 0, madera_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + +SND_SOC_DAPM_MUX("HPOUT1L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l90_output_anc_src[0]), +SND_SOC_DAPM_MUX("HPOUT1R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l90_output_anc_src[1]), +SND_SOC_DAPM_MUX("HPOUT2L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l90_output_anc_src[2]), +SND_SOC_DAPM_MUX("HPOUT2R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l90_output_anc_src[3]), +SND_SOC_DAPM_MUX("HPOUT3L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l90_output_anc_src[4]), +SND_SOC_DAPM_MUX("HPOUT3R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l90_output_anc_src[5]), +SND_SOC_DAPM_MUX("SPKDAT1L ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l90_output_anc_src[6]), +SND_SOC_DAPM_MUX("SPKDAT1R ANC Source", SND_SOC_NOPM, 0, 0, + &cs47l90_output_anc_src[7]), + +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF4TX1", NULL, 0, + MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 0, + MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, + MADERA_OUT1L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, + MADERA_OUT1R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2L", SND_SOC_NOPM, + MADERA_OUT2L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2R", SND_SOC_NOPM, + MADERA_OUT2R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3L", SND_SOC_NOPM, + MADERA_OUT3L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3R", SND_SOC_NOPM, + MADERA_OUT3R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("SPD1TX1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL1_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("SPD1TX2", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL2_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_OUT_DRV("SPD1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_ENA_SHIFT, 0, NULL, 0), + +/* + * mux_in widgets : arranged in the order of sources + * specified in MADERA_MIXER_INPUT_ROUTES + */ + +SND_SOC_DAPM_PGA("Noise Generator", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Tone Generator 1", MADERA_TONE_GENERATOR_1, + MADERA_TONE1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("Tone Generator 2", MADERA_TONE_GENERATOR_1, + MADERA_TONE2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SIGGEN("HAPTICS"), + +SND_SOC_DAPM_MUX("AEC1 Loopback", MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_ENA_SHIFT, 0, + &cs47l90_aec_loopback_mux[0]), +SND_SOC_DAPM_MUX("AEC2 Loopback", MADERA_DAC_AEC_CONTROL_2, + MADERA_AEC2_LOOPBACK_ENA_SHIFT, 0, + &cs47l90_aec_loopback_mux[1]), + +SND_SOC_DAPM_PGA_E("IN1L", MADERA_INPUT_ENABLES, MADERA_IN1L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN1R", MADERA_INPUT_ENABLES, MADERA_IN1R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2L", MADERA_INPUT_ENABLES, MADERA_IN2L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3L", MADERA_INPUT_ENABLES, MADERA_IN3L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3R", MADERA_INPUT_ENABLES, MADERA_IN3R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4L", MADERA_INPUT_ENABLES, MADERA_IN4L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4R", MADERA_INPUT_ENABLES, MADERA_IN4R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN5L", MADERA_INPUT_ENABLES, MADERA_IN5L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN5R", MADERA_INPUT_ENABLES, MADERA_IN5R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF4RX1", NULL, 0, + MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 0, + MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ2", MADERA_EQ2_1, MADERA_EQ2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ3", MADERA_EQ3_1, MADERA_EQ3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ4", MADERA_EQ4_1, MADERA_EQ4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("DRC1L", MADERA_DRC1_CTRL1, MADERA_DRC1L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC1R", MADERA_DRC1_CTRL1, MADERA_DRC1R_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2L", MADERA_DRC2_CTRL1, MADERA_DRC2L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2R", MADERA_DRC2_CTRL1, MADERA_DRC2R_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("LHPF1", MADERA_HPLPF1_1, MADERA_LHPF1_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF2", MADERA_HPLPF2_1, MADERA_LHPF2_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF3", MADERA_HPLPF3_1, MADERA_LHPF3_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF4", MADERA_HPLPF4_1, MADERA_LHPF4_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("ASRC1IN1L", MADERA_ASRC1_ENABLE, + MADERA_ASRC1_IN1L_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN1R", MADERA_ASRC1_ENABLE, + MADERA_ASRC1_IN1R_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN2L", MADERA_ASRC1_ENABLE, + MADERA_ASRC1_IN2L_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN2R", MADERA_ASRC1_ENABLE, + MADERA_ASRC1_IN2R_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ASRC2IN1L", MADERA_ASRC2_ENABLE, + MADERA_ASRC2_IN1L_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC2IN1R", MADERA_ASRC2_ENABLE, + MADERA_ASRC2_IN1R_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC2IN2L", MADERA_ASRC2_ENABLE, + MADERA_ASRC2_IN2L_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC2IN2R", MADERA_ASRC2_ENABLE, + MADERA_ASRC2_IN2R_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1DEC1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC3", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC4", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1INT1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT3", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT4", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2DEC1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC3", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC4", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2INT1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT3", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT4", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC3DEC1", MADERA_ISRC_3_CTRL_3, + MADERA_ISRC3_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC3DEC2", MADERA_ISRC_3_CTRL_3, + MADERA_ISRC3_DEC2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC3INT1", MADERA_ISRC_3_CTRL_3, + MADERA_ISRC3_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC3INT2", MADERA_ISRC_3_CTRL_3, + MADERA_ISRC3_INT2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC4DEC1", MADERA_ISRC_4_CTRL_3, + MADERA_ISRC4_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC4DEC2", MADERA_ISRC_4_CTRL_3, + MADERA_ISRC4_DEC2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC4INT1", MADERA_ISRC_4_CTRL_3, + MADERA_ISRC4_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC4INT2", MADERA_ISRC_4_CTRL_3, + MADERA_ISRC4_INT2_ENA_SHIFT, 0, NULL, 0), + +WM_ADSP2("DSP1", 0, cs47l90_adsp_power_ev), +WM_ADSP2("DSP2", 1, cs47l90_adsp_power_ev), +WM_ADSP2("DSP3", 2, cs47l90_adsp_power_ev), +WM_ADSP2("DSP4", 3, cs47l90_adsp_power_ev), +WM_ADSP2("DSP5", 4, cs47l90_adsp_power_ev), +WM_ADSP2("DSP6", 5, cs47l90_adsp_power_ev), +WM_ADSP2("DSP7", 6, cs47l90_adsp_power_ev), + +/* end of ordered widget list */ + +SND_SOC_DAPM_PGA("DFC1", MADERA_DFC1_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC2", MADERA_DFC2_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC3", MADERA_DFC3_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC4", MADERA_DFC4_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC5", MADERA_DFC5_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC6", MADERA_DFC6_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC7", MADERA_DFC7_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC8", MADERA_DFC8_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), + +MADERA_MIXER_WIDGETS(EQ1, "EQ1"), +MADERA_MIXER_WIDGETS(EQ2, "EQ2"), +MADERA_MIXER_WIDGETS(EQ3, "EQ3"), +MADERA_MIXER_WIDGETS(EQ4, "EQ4"), + +MADERA_MIXER_WIDGETS(DRC1L, "DRC1L"), +MADERA_MIXER_WIDGETS(DRC1R, "DRC1R"), +MADERA_MIXER_WIDGETS(DRC2L, "DRC2L"), +MADERA_MIXER_WIDGETS(DRC2R, "DRC2R"), + +SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[0]), +SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[1]), + +MADERA_MIXER_WIDGETS(LHPF1, "LHPF1"), +MADERA_MIXER_WIDGETS(LHPF2, "LHPF2"), +MADERA_MIXER_WIDGETS(LHPF3, "LHPF3"), +MADERA_MIXER_WIDGETS(LHPF4, "LHPF4"), + +MADERA_MIXER_WIDGETS(PWM1, "PWM1"), +MADERA_MIXER_WIDGETS(PWM2, "PWM2"), + +MADERA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), +MADERA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), +MADERA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), +MADERA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), +MADERA_MIXER_WIDGETS(OUT3L, "HPOUT3L"), +MADERA_MIXER_WIDGETS(OUT3R, "HPOUT3R"), +MADERA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), +MADERA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), + +MADERA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), +MADERA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), +MADERA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), +MADERA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), +MADERA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), +MADERA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), +MADERA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), +MADERA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), + +MADERA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), +MADERA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), +MADERA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), +MADERA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), +MADERA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"), +MADERA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"), +MADERA_MIXER_WIDGETS(AIF2TX7, "AIF2TX7"), +MADERA_MIXER_WIDGETS(AIF2TX8, "AIF2TX8"), + +MADERA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), +MADERA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), + +MADERA_MIXER_WIDGETS(AIF4TX1, "AIF4TX1"), +MADERA_MIXER_WIDGETS(AIF4TX2, "AIF4TX2"), + +MADERA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), +MADERA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), +MADERA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), +MADERA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), +MADERA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), +MADERA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), +MADERA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), +MADERA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), + +MADERA_MUX_WIDGETS(SPD1TX1, "SPDIF1TX1"), +MADERA_MUX_WIDGETS(SPD1TX2, "SPDIF1TX2"), + +MADERA_MUX_WIDGETS(ASRC1IN1L, "ASRC1IN1L"), +MADERA_MUX_WIDGETS(ASRC1IN1R, "ASRC1IN1R"), +MADERA_MUX_WIDGETS(ASRC1IN2L, "ASRC1IN2L"), +MADERA_MUX_WIDGETS(ASRC1IN2R, "ASRC1IN2R"), +MADERA_MUX_WIDGETS(ASRC2IN1L, "ASRC2IN1L"), +MADERA_MUX_WIDGETS(ASRC2IN1R, "ASRC2IN1R"), +MADERA_MUX_WIDGETS(ASRC2IN2L, "ASRC2IN2L"), +MADERA_MUX_WIDGETS(ASRC2IN2R, "ASRC2IN2R"), + +MADERA_DSP_WIDGETS(DSP1, "DSP1"), +MADERA_DSP_WIDGETS(DSP2, "DSP2"), +MADERA_DSP_WIDGETS(DSP3, "DSP3"), +MADERA_DSP_WIDGETS(DSP4, "DSP4"), +MADERA_DSP_WIDGETS(DSP5, "DSP5"), +MADERA_DSP_WIDGETS(DSP6, "DSP6"), +MADERA_DSP_WIDGETS(DSP7, "DSP7"), + +SND_SOC_DAPM_SWITCH("DSP1 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[0]), +SND_SOC_DAPM_SWITCH("DSP2 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[1]), +SND_SOC_DAPM_SWITCH("DSP3 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[2]), +SND_SOC_DAPM_SWITCH("DSP4 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[3]), +SND_SOC_DAPM_SWITCH("DSP5 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[4]), +SND_SOC_DAPM_SWITCH("DSP6 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[5]), +SND_SOC_DAPM_SWITCH("DSP7 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[6]), + +MADERA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), +MADERA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), +MADERA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), +MADERA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), + +MADERA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), +MADERA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), +MADERA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), +MADERA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), + +MADERA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), +MADERA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), +MADERA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"), +MADERA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"), + +MADERA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), +MADERA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), +MADERA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"), +MADERA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"), + +MADERA_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"), +MADERA_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"), + +MADERA_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"), +MADERA_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"), + +MADERA_MUX_WIDGETS(ISRC4DEC1, "ISRC4DEC1"), +MADERA_MUX_WIDGETS(ISRC4DEC2, "ISRC4DEC2"), + +MADERA_MUX_WIDGETS(ISRC4INT1, "ISRC4INT1"), +MADERA_MUX_WIDGETS(ISRC4INT2, "ISRC4INT2"), + +MADERA_MUX_WIDGETS(DFC1, "DFC1"), +MADERA_MUX_WIDGETS(DFC2, "DFC2"), +MADERA_MUX_WIDGETS(DFC3, "DFC3"), +MADERA_MUX_WIDGETS(DFC4, "DFC4"), +MADERA_MUX_WIDGETS(DFC5, "DFC5"), +MADERA_MUX_WIDGETS(DFC6, "DFC6"), +MADERA_MUX_WIDGETS(DFC7, "DFC7"), +MADERA_MUX_WIDGETS(DFC8, "DFC8"), + +SND_SOC_DAPM_OUTPUT("HPOUT1L"), +SND_SOC_DAPM_OUTPUT("HPOUT1R"), +SND_SOC_DAPM_OUTPUT("HPOUT2L"), +SND_SOC_DAPM_OUTPUT("HPOUT2R"), +SND_SOC_DAPM_OUTPUT("HPOUT3L"), +SND_SOC_DAPM_OUTPUT("HPOUT3R"), +SND_SOC_DAPM_OUTPUT("SPKDAT1L"), +SND_SOC_DAPM_OUTPUT("SPKDAT1R"), +SND_SOC_DAPM_OUTPUT("SPDIF1"), + +SND_SOC_DAPM_OUTPUT("MICSUPP"), +}; + +#define MADERA_MIXER_INPUT_ROUTES(name) \ + { name, "Noise Generator", "Noise Generator" }, \ + { name, "Tone Generator 1", "Tone Generator 1" }, \ + { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "Haptics", "HAPTICS" }, \ + { name, "AEC1", "AEC1 Loopback" }, \ + { name, "AEC2", "AEC2 Loopback" }, \ + { name, "IN1L", "IN1L" }, \ + { name, "IN1R", "IN1R" }, \ + { name, "IN2L", "IN2L" }, \ + { name, "IN2R", "IN2R" }, \ + { name, "IN3L", "IN3L" }, \ + { name, "IN3R", "IN3R" }, \ + { name, "IN4L", "IN4L" }, \ + { name, "IN4R", "IN4R" }, \ + { name, "IN5L", "IN5L" }, \ + { name, "IN5R", "IN5R" }, \ + { name, "AIF1RX1", "AIF1RX1" }, \ + { name, "AIF1RX2", "AIF1RX2" }, \ + { name, "AIF1RX3", "AIF1RX3" }, \ + { name, "AIF1RX4", "AIF1RX4" }, \ + { name, "AIF1RX5", "AIF1RX5" }, \ + { name, "AIF1RX6", "AIF1RX6" }, \ + { name, "AIF1RX7", "AIF1RX7" }, \ + { name, "AIF1RX8", "AIF1RX8" }, \ + { name, "AIF2RX1", "AIF2RX1" }, \ + { name, "AIF2RX2", "AIF2RX2" }, \ + { name, "AIF2RX3", "AIF2RX3" }, \ + { name, "AIF2RX4", "AIF2RX4" }, \ + { name, "AIF2RX5", "AIF2RX5" }, \ + { name, "AIF2RX6", "AIF2RX6" }, \ + { name, "AIF2RX7", "AIF2RX7" }, \ + { name, "AIF2RX8", "AIF2RX8" }, \ + { name, "AIF3RX1", "AIF3RX1" }, \ + { name, "AIF3RX2", "AIF3RX2" }, \ + { name, "AIF4RX1", "AIF4RX1" }, \ + { name, "AIF4RX2", "AIF4RX2" }, \ + { name, "SLIMRX1", "SLIMRX1" }, \ + { name, "SLIMRX2", "SLIMRX2" }, \ + { name, "SLIMRX3", "SLIMRX3" }, \ + { name, "SLIMRX4", "SLIMRX4" }, \ + { name, "SLIMRX5", "SLIMRX5" }, \ + { name, "SLIMRX6", "SLIMRX6" }, \ + { name, "SLIMRX7", "SLIMRX7" }, \ + { name, "SLIMRX8", "SLIMRX8" }, \ + { name, "EQ1", "EQ1" }, \ + { name, "EQ2", "EQ2" }, \ + { name, "EQ3", "EQ3" }, \ + { name, "EQ4", "EQ4" }, \ + { name, "DRC1L", "DRC1L" }, \ + { name, "DRC1R", "DRC1R" }, \ + { name, "DRC2L", "DRC2L" }, \ + { name, "DRC2R", "DRC2R" }, \ + { name, "LHPF1", "LHPF1" }, \ + { name, "LHPF2", "LHPF2" }, \ + { name, "LHPF3", "LHPF3" }, \ + { name, "LHPF4", "LHPF4" }, \ + { name, "ASRC1IN1L", "ASRC1IN1L" }, \ + { name, "ASRC1IN1R", "ASRC1IN1R" }, \ + { name, "ASRC1IN2L", "ASRC1IN2L" }, \ + { name, "ASRC1IN2R", "ASRC1IN2R" }, \ + { name, "ASRC2IN1L", "ASRC2IN1L" }, \ + { name, "ASRC2IN1R", "ASRC2IN1R" }, \ + { name, "ASRC2IN2L", "ASRC2IN2L" }, \ + { name, "ASRC2IN2R", "ASRC2IN2R" }, \ + { name, "ISRC1DEC1", "ISRC1DEC1" }, \ + { name, "ISRC1DEC2", "ISRC1DEC2" }, \ + { name, "ISRC1DEC3", "ISRC1DEC3" }, \ + { name, "ISRC1DEC4", "ISRC1DEC4" }, \ + { name, "ISRC1INT1", "ISRC1INT1" }, \ + { name, "ISRC1INT2", "ISRC1INT2" }, \ + { name, "ISRC1INT3", "ISRC1INT3" }, \ + { name, "ISRC1INT4", "ISRC1INT4" }, \ + { name, "ISRC2DEC1", "ISRC2DEC1" }, \ + { name, "ISRC2DEC2", "ISRC2DEC2" }, \ + { name, "ISRC2DEC3", "ISRC2DEC3" }, \ + { name, "ISRC2DEC4", "ISRC2DEC4" }, \ + { name, "ISRC2INT1", "ISRC2INT1" }, \ + { name, "ISRC2INT2", "ISRC2INT2" }, \ + { name, "ISRC2INT3", "ISRC2INT3" }, \ + { name, "ISRC2INT4", "ISRC2INT4" }, \ + { name, "ISRC3DEC1", "ISRC3DEC1" }, \ + { name, "ISRC3DEC2", "ISRC3DEC2" }, \ + { name, "ISRC3INT1", "ISRC3INT1" }, \ + { name, "ISRC3INT2", "ISRC3INT2" }, \ + { name, "ISRC4DEC1", "ISRC4DEC1" }, \ + { name, "ISRC4DEC2", "ISRC4DEC2" }, \ + { name, "ISRC4INT1", "ISRC4INT1" }, \ + { name, "ISRC4INT2", "ISRC4INT2" }, \ + { name, "DSP1.1", "DSP1" }, \ + { name, "DSP1.2", "DSP1" }, \ + { name, "DSP1.3", "DSP1" }, \ + { name, "DSP1.4", "DSP1" }, \ + { name, "DSP1.5", "DSP1" }, \ + { name, "DSP1.6", "DSP1" }, \ + { name, "DSP2.1", "DSP2" }, \ + { name, "DSP2.2", "DSP2" }, \ + { name, "DSP2.3", "DSP2" }, \ + { name, "DSP2.4", "DSP2" }, \ + { name, "DSP2.5", "DSP2" }, \ + { name, "DSP2.6", "DSP2" }, \ + { name, "DSP3.1", "DSP3" }, \ + { name, "DSP3.2", "DSP3" }, \ + { name, "DSP3.3", "DSP3" }, \ + { name, "DSP3.4", "DSP3" }, \ + { name, "DSP3.5", "DSP3" }, \ + { name, "DSP3.6", "DSP3" }, \ + { name, "DSP4.1", "DSP4" }, \ + { name, "DSP4.2", "DSP4" }, \ + { name, "DSP4.3", "DSP4" }, \ + { name, "DSP4.4", "DSP4" }, \ + { name, "DSP4.5", "DSP4" }, \ + { name, "DSP4.6", "DSP4" }, \ + { name, "DSP5.1", "DSP5" }, \ + { name, "DSP5.2", "DSP5" }, \ + { name, "DSP5.3", "DSP5" }, \ + { name, "DSP5.4", "DSP5" }, \ + { name, "DSP5.5", "DSP5" }, \ + { name, "DSP5.6", "DSP5" }, \ + { name, "DSP6.1", "DSP6" }, \ + { name, "DSP6.2", "DSP6" }, \ + { name, "DSP6.3", "DSP6" }, \ + { name, "DSP6.4", "DSP6" }, \ + { name, "DSP6.5", "DSP6" }, \ + { name, "DSP6.6", "DSP6" }, \ + { name, "DSP7.1", "DSP7" }, \ + { name, "DSP7.2", "DSP7" }, \ + { name, "DSP7.3", "DSP7" }, \ + { name, "DSP7.4", "DSP7" }, \ + { name, "DSP7.5", "DSP7" }, \ + { name, "DSP7.6", "DSP7" }, \ + { name, "DFC1", "DFC1" }, \ + { name, "DFC2", "DFC2" }, \ + { name, "DFC3", "DFC3" }, \ + { name, "DFC4", "DFC4" }, \ + { name, "DFC5", "DFC5" }, \ + { name, "DFC6", "DFC6" }, \ + { name, "DFC7", "DFC7" }, \ + { name, "DFC8", "DFC8" } + +static const struct snd_soc_dapm_route cs47l90_dapm_routes[] = { + /* Internal clock domains */ + { "EQ1", NULL, "FXCLK" }, + { "EQ2", NULL, "FXCLK" }, + { "EQ3", NULL, "FXCLK" }, + { "EQ4", NULL, "FXCLK" }, + { "DRC1L", NULL, "FXCLK" }, + { "DRC1R", NULL, "FXCLK" }, + { "DRC2L", NULL, "FXCLK" }, + { "DRC2R", NULL, "FXCLK" }, + { "LHPF1", NULL, "FXCLK" }, + { "LHPF2", NULL, "FXCLK" }, + { "LHPF3", NULL, "FXCLK" }, + { "LHPF4", NULL, "FXCLK" }, + { "PWM1 Mixer", NULL, "PWMCLK" }, + { "PWM2 Mixer", NULL, "PWMCLK" }, + { "OUT1L", NULL, "OUTCLK" }, + { "OUT1R", NULL, "OUTCLK" }, + { "OUT2L", NULL, "OUTCLK" }, + { "OUT2R", NULL, "OUTCLK" }, + { "OUT3L", NULL, "OUTCLK" }, + { "OUT3R", NULL, "OUTCLK" }, + { "OUT5L", NULL, "OUTCLK" }, + { "OUT5R", NULL, "OUTCLK" }, + { "AIF1TX1", NULL, "AIF1TXCLK" }, + { "AIF1TX2", NULL, "AIF1TXCLK" }, + { "AIF1TX3", NULL, "AIF1TXCLK" }, + { "AIF1TX4", NULL, "AIF1TXCLK" }, + { "AIF1TX5", NULL, "AIF1TXCLK" }, + { "AIF1TX6", NULL, "AIF1TXCLK" }, + { "AIF1TX7", NULL, "AIF1TXCLK" }, + { "AIF1TX8", NULL, "AIF1TXCLK" }, + { "AIF2TX1", NULL, "AIF2TXCLK" }, + { "AIF2TX2", NULL, "AIF2TXCLK" }, + { "AIF2TX3", NULL, "AIF2TXCLK" }, + { "AIF2TX4", NULL, "AIF2TXCLK" }, + { "AIF2TX5", NULL, "AIF2TXCLK" }, + { "AIF2TX6", NULL, "AIF2TXCLK" }, + { "AIF2TX7", NULL, "AIF2TXCLK" }, + { "AIF2TX8", NULL, "AIF2TXCLK" }, + { "AIF3TX1", NULL, "AIF3TXCLK" }, + { "AIF3TX2", NULL, "AIF3TXCLK" }, + { "AIF4TX1", NULL, "AIF4TXCLK" }, + { "AIF4TX2", NULL, "AIF4TXCLK" }, + { "SLIMTX1", NULL, "SLIMBUSCLK" }, + { "SLIMTX2", NULL, "SLIMBUSCLK" }, + { "SLIMTX3", NULL, "SLIMBUSCLK" }, + { "SLIMTX4", NULL, "SLIMBUSCLK" }, + { "SLIMTX5", NULL, "SLIMBUSCLK" }, + { "SLIMTX6", NULL, "SLIMBUSCLK" }, + { "SLIMTX7", NULL, "SLIMBUSCLK" }, + { "SLIMTX8", NULL, "SLIMBUSCLK" }, + { "SPD1TX1", NULL, "SPDCLK" }, + { "SPD1TX2", NULL, "SPDCLK" }, + { "DSP1", NULL, "DSP1CLK" }, + { "DSP2", NULL, "DSP2CLK" }, + { "DSP3", NULL, "DSP3CLK" }, + { "DSP4", NULL, "DSP4CLK" }, + { "DSP5", NULL, "DSP5CLK" }, + { "DSP6", NULL, "DSP6CLK" }, + { "DSP7", NULL, "DSP7CLK" }, + { "ISRC1DEC1", NULL, "ISRC1CLK" }, + { "ISRC1DEC2", NULL, "ISRC1CLK" }, + { "ISRC1DEC3", NULL, "ISRC1CLK" }, + { "ISRC1DEC4", NULL, "ISRC1CLK" }, + { "ISRC1INT1", NULL, "ISRC1CLK" }, + { "ISRC1INT2", NULL, "ISRC1CLK" }, + { "ISRC1INT3", NULL, "ISRC1CLK" }, + { "ISRC1INT4", NULL, "ISRC1CLK" }, + { "ISRC2DEC1", NULL, "ISRC2CLK" }, + { "ISRC2DEC2", NULL, "ISRC2CLK" }, + { "ISRC2DEC3", NULL, "ISRC2CLK" }, + { "ISRC2DEC4", NULL, "ISRC2CLK" }, + { "ISRC2INT1", NULL, "ISRC2CLK" }, + { "ISRC2INT2", NULL, "ISRC2CLK" }, + { "ISRC2INT3", NULL, "ISRC2CLK" }, + { "ISRC2INT4", NULL, "ISRC2CLK" }, + { "ISRC3DEC1", NULL, "ISRC3CLK" }, + { "ISRC3DEC2", NULL, "ISRC3CLK" }, + { "ISRC3INT1", NULL, "ISRC3CLK" }, + { "ISRC3INT2", NULL, "ISRC3CLK" }, + { "ISRC4DEC1", NULL, "ISRC4CLK" }, + { "ISRC4DEC2", NULL, "ISRC4CLK" }, + { "ISRC4INT1", NULL, "ISRC4CLK" }, + { "ISRC4INT2", NULL, "ISRC4CLK" }, + { "ASRC1IN1L", NULL, "ASRC1CLK" }, + { "ASRC1IN1R", NULL, "ASRC1CLK" }, + { "ASRC1IN2L", NULL, "ASRC1CLK" }, + { "ASRC1IN2R", NULL, "ASRC1CLK" }, + { "ASRC2IN1L", NULL, "ASRC2CLK" }, + { "ASRC2IN1R", NULL, "ASRC2CLK" }, + { "ASRC2IN2L", NULL, "ASRC2CLK" }, + { "ASRC2IN2R", NULL, "ASRC2CLK" }, + { "DFC1", NULL, "DFCCLK" }, + { "DFC2", NULL, "DFCCLK" }, + { "DFC3", NULL, "DFCCLK" }, + { "DFC4", NULL, "DFCCLK" }, + { "DFC5", NULL, "DFCCLK" }, + { "DFC6", NULL, "DFCCLK" }, + { "DFC7", NULL, "DFCCLK" }, + { "DFC8", NULL, "DFCCLK" }, + + { "AIF2 Capture", NULL, "DBVDD2" }, + { "AIF2 Playback", NULL, "DBVDD2" }, + + { "AIF3 Capture", NULL, "DBVDD3" }, + { "AIF3 Playback", NULL, "DBVDD3" }, + + { "AIF4 Capture", NULL, "DBVDD3" }, + { "AIF4 Playback", NULL, "DBVDD3" }, + + { "OUT1L", NULL, "CPVDD1" }, + { "OUT1L", NULL, "CPVDD2" }, + { "OUT1R", NULL, "CPVDD1" }, + { "OUT1R", NULL, "CPVDD2" }, + { "OUT2L", NULL, "CPVDD1" }, + { "OUT2L", NULL, "CPVDD2" }, + { "OUT2R", NULL, "CPVDD1" }, + { "OUT2R", NULL, "CPVDD2" }, + { "OUT3L", NULL, "CPVDD1" }, + { "OUT3L", NULL, "CPVDD2" }, + { "OUT3R", NULL, "CPVDD1" }, + { "OUT3R", NULL, "CPVDD2" }, + + { "OUT1L", NULL, "SYSCLK" }, + { "OUT1R", NULL, "SYSCLK" }, + { "OUT2L", NULL, "SYSCLK" }, + { "OUT2R", NULL, "SYSCLK" }, + { "OUT3L", NULL, "SYSCLK" }, + { "OUT3R", NULL, "SYSCLK" }, + { "OUT5L", NULL, "SYSCLK" }, + { "OUT5R", NULL, "SYSCLK" }, + + { "SPD1", NULL, "SYSCLK" }, + { "SPD1", NULL, "SPD1TX1" }, + { "SPD1", NULL, "SPD1TX2" }, + + { "IN1L", NULL, "SYSCLK" }, + { "IN1R", NULL, "SYSCLK" }, + { "IN2L", NULL, "SYSCLK" }, + { "IN2R", NULL, "SYSCLK" }, + { "IN3L", NULL, "SYSCLK" }, + { "IN3R", NULL, "SYSCLK" }, + { "IN4L", NULL, "SYSCLK" }, + { "IN4R", NULL, "SYSCLK" }, + { "IN5L", NULL, "SYSCLK" }, + { "IN5R", NULL, "SYSCLK" }, + + { "IN3L", NULL, "DBVDD4" }, + { "IN3R", NULL, "DBVDD4" }, + { "IN4L", NULL, "DBVDD4" }, + { "IN4R", NULL, "DBVDD4" }, + { "IN5L", NULL, "DBVDD4" }, + { "IN5R", NULL, "DBVDD4" }, + + { "ASRC1IN1L", NULL, "SYSCLK" }, + { "ASRC1IN1R", NULL, "SYSCLK" }, + { "ASRC1IN2L", NULL, "SYSCLK" }, + { "ASRC1IN2R", NULL, "SYSCLK" }, + { "ASRC2IN1L", NULL, "SYSCLK" }, + { "ASRC2IN1R", NULL, "SYSCLK" }, + { "ASRC2IN2L", NULL, "SYSCLK" }, + { "ASRC2IN2R", NULL, "SYSCLK" }, + + { "ASRC1IN1L", NULL, "ASYNCCLK" }, + { "ASRC1IN1R", NULL, "ASYNCCLK" }, + { "ASRC1IN2L", NULL, "ASYNCCLK" }, + { "ASRC1IN2R", NULL, "ASYNCCLK" }, + { "ASRC2IN1L", NULL, "ASYNCCLK" }, + { "ASRC2IN1R", NULL, "ASYNCCLK" }, + { "ASRC2IN2L", NULL, "ASYNCCLK" }, + { "ASRC2IN2R", NULL, "ASYNCCLK" }, + + { "MICBIAS1", NULL, "MICVDD" }, + { "MICBIAS2", NULL, "MICVDD" }, + + { "MICBIAS1A", NULL, "MICBIAS1" }, + { "MICBIAS1B", NULL, "MICBIAS1" }, + { "MICBIAS1C", NULL, "MICBIAS1" }, + { "MICBIAS1D", NULL, "MICBIAS1" }, + + { "MICBIAS2A", NULL, "MICBIAS2" }, + { "MICBIAS2B", NULL, "MICBIAS2" }, + { "MICBIAS2C", NULL, "MICBIAS2" }, + { "MICBIAS2D", NULL, "MICBIAS2" }, + + { "Noise Generator", NULL, "SYSCLK" }, + { "Tone Generator 1", NULL, "SYSCLK" }, + { "Tone Generator 2", NULL, "SYSCLK" }, + + { "Noise Generator", NULL, "NOISE" }, + { "Tone Generator 1", NULL, "TONE" }, + { "Tone Generator 2", NULL, "TONE" }, + + { "AIF1 Capture", NULL, "AIF1TX1" }, + { "AIF1 Capture", NULL, "AIF1TX2" }, + { "AIF1 Capture", NULL, "AIF1TX3" }, + { "AIF1 Capture", NULL, "AIF1TX4" }, + { "AIF1 Capture", NULL, "AIF1TX5" }, + { "AIF1 Capture", NULL, "AIF1TX6" }, + { "AIF1 Capture", NULL, "AIF1TX7" }, + { "AIF1 Capture", NULL, "AIF1TX8" }, + + { "AIF1RX1", NULL, "AIF1 Playback" }, + { "AIF1RX2", NULL, "AIF1 Playback" }, + { "AIF1RX3", NULL, "AIF1 Playback" }, + { "AIF1RX4", NULL, "AIF1 Playback" }, + { "AIF1RX5", NULL, "AIF1 Playback" }, + { "AIF1RX6", NULL, "AIF1 Playback" }, + { "AIF1RX7", NULL, "AIF1 Playback" }, + { "AIF1RX8", NULL, "AIF1 Playback" }, + + { "AIF2 Capture", NULL, "AIF2TX1" }, + { "AIF2 Capture", NULL, "AIF2TX2" }, + { "AIF2 Capture", NULL, "AIF2TX3" }, + { "AIF2 Capture", NULL, "AIF2TX4" }, + { "AIF2 Capture", NULL, "AIF2TX5" }, + { "AIF2 Capture", NULL, "AIF2TX6" }, + { "AIF2 Capture", NULL, "AIF2TX7" }, + { "AIF2 Capture", NULL, "AIF2TX8" }, + + { "AIF2RX1", NULL, "AIF2 Playback" }, + { "AIF2RX2", NULL, "AIF2 Playback" }, + { "AIF2RX3", NULL, "AIF2 Playback" }, + { "AIF2RX4", NULL, "AIF2 Playback" }, + { "AIF2RX5", NULL, "AIF2 Playback" }, + { "AIF2RX6", NULL, "AIF2 Playback" }, + { "AIF2RX7", NULL, "AIF2 Playback" }, + { "AIF2RX8", NULL, "AIF2 Playback" }, + + { "AIF3 Capture", NULL, "AIF3TX1" }, + { "AIF3 Capture", NULL, "AIF3TX2" }, + + { "AIF3RX1", NULL, "AIF3 Playback" }, + { "AIF3RX2", NULL, "AIF3 Playback" }, + + { "AIF4 Capture", NULL, "AIF4TX1" }, + { "AIF4 Capture", NULL, "AIF4TX2" }, + + { "AIF4RX1", NULL, "AIF4 Playback" }, + { "AIF4RX2", NULL, "AIF4 Playback" }, + + { "Slim1 Capture", NULL, "SLIMTX1" }, + { "Slim1 Capture", NULL, "SLIMTX2" }, + { "Slim1 Capture", NULL, "SLIMTX3" }, + { "Slim1 Capture", NULL, "SLIMTX4" }, + + { "SLIMRX1", NULL, "Slim1 Playback" }, + { "SLIMRX2", NULL, "Slim1 Playback" }, + { "SLIMRX3", NULL, "Slim1 Playback" }, + { "SLIMRX4", NULL, "Slim1 Playback" }, + + { "Slim2 Capture", NULL, "SLIMTX5" }, + { "Slim2 Capture", NULL, "SLIMTX6" }, + + { "SLIMRX5", NULL, "Slim2 Playback" }, + { "SLIMRX6", NULL, "Slim2 Playback" }, + + { "Slim3 Capture", NULL, "SLIMTX7" }, + { "Slim3 Capture", NULL, "SLIMTX8" }, + + { "SLIMRX7", NULL, "Slim3 Playback" }, + { "SLIMRX8", NULL, "Slim3 Playback" }, + + { "AIF1 Playback", NULL, "SYSCLK" }, + { "AIF2 Playback", NULL, "SYSCLK" }, + { "AIF3 Playback", NULL, "SYSCLK" }, + { "AIF4 Playback", NULL, "SYSCLK" }, + { "Slim1 Playback", NULL, "SYSCLK" }, + { "Slim2 Playback", NULL, "SYSCLK" }, + { "Slim3 Playback", NULL, "SYSCLK" }, + + { "AIF1 Capture", NULL, "SYSCLK" }, + { "AIF2 Capture", NULL, "SYSCLK" }, + { "AIF3 Capture", NULL, "SYSCLK" }, + { "AIF4 Capture", NULL, "SYSCLK" }, + { "Slim1 Capture", NULL, "SYSCLK" }, + { "Slim2 Capture", NULL, "SYSCLK" }, + { "Slim3 Capture", NULL, "SYSCLK" }, + + { "Voice Control DSP", NULL, "DSP6" }, + + { "Audio Trace DSP", NULL, "DSP1" }, + + { "IN1L Analog Mux", "A", "IN1ALN" }, + { "IN1L Analog Mux", "A", "IN1ALP" }, + { "IN1L Analog Mux", "B", "IN1BLN" }, + { "IN1L Analog Mux", "B", "IN1BLP" }, + { "IN1R Analog Mux", "A", "IN1ARN" }, + { "IN1R Analog Mux", "A", "IN1ARP" }, + { "IN1R Analog Mux", "B", "IN1BRN" }, + { "IN1R Analog Mux", "B", "IN1BRP" }, + + { "IN1L Mode", "Analog", "IN1L Analog Mux" }, + { "IN1R Mode", "Analog", "IN1R Analog Mux" }, + + { "IN1L Mode", "Digital", "IN1ARN" }, + { "IN1L Mode", "Digital", "IN1ARP" }, + { "IN1R Mode", "Digital", "IN1ARN" }, + { "IN1R Mode", "Digital", "IN1ARP" }, + + { "IN1L", NULL, "IN1L Mode" }, + { "IN1R", NULL, "IN1R Mode" }, + + { "IN2L Analog Mux", "A", "IN2ALN" }, + { "IN2L Analog Mux", "A", "IN2ALP" }, + { "IN2L Analog Mux", "B", "IN2BLN" }, + { "IN2L Analog Mux", "B", "IN2BLP" }, + + { "IN2L Mode", "Analog", "IN2L Analog Mux" }, + { "IN2R Mode", "Analog", "IN2RN" }, + { "IN2R Mode", "Analog", "IN2RP" }, + + { "IN2L Mode", "Digital", "IN2ALN" }, + { "IN2L Mode", "Digital", "IN2ALP" }, + { "IN2R Mode", "Digital", "IN2ALN" }, + { "IN2R Mode", "Digital", "IN2ALP" }, + + { "IN2L", NULL, "IN2L Mode" }, + { "IN2R", NULL, "IN2R Mode" }, + + { "IN3L", NULL, "DMICCLK3" }, + { "IN3R", NULL, "DMICDAT3" }, + + { "IN4L", NULL, "DMICCLK4" }, + { "IN4R", NULL, "DMICDAT4" }, + + { "IN5L", NULL, "DMICCLK5" }, + { "IN5R", NULL, "DMICDAT5" }, + + MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"), + MADERA_MIXER_ROUTES("OUT1R", "HPOUT1R"), + MADERA_MIXER_ROUTES("OUT2L", "HPOUT2L"), + MADERA_MIXER_ROUTES("OUT2R", "HPOUT2R"), + MADERA_MIXER_ROUTES("OUT3L", "HPOUT3L"), + MADERA_MIXER_ROUTES("OUT3R", "HPOUT3R"), + + MADERA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), + MADERA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), + + MADERA_MIXER_ROUTES("PWM1 Driver", "PWM1"), + MADERA_MIXER_ROUTES("PWM2 Driver", "PWM2"), + + MADERA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), + MADERA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), + MADERA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), + MADERA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), + MADERA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), + MADERA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), + MADERA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), + MADERA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), + + MADERA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), + MADERA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), + MADERA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), + MADERA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), + MADERA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"), + MADERA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"), + MADERA_MIXER_ROUTES("AIF2TX7", "AIF2TX7"), + MADERA_MIXER_ROUTES("AIF2TX8", "AIF2TX8"), + + MADERA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), + MADERA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), + + MADERA_MIXER_ROUTES("AIF4TX1", "AIF4TX1"), + MADERA_MIXER_ROUTES("AIF4TX2", "AIF4TX2"), + + MADERA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), + MADERA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), + MADERA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), + MADERA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), + MADERA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), + MADERA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), + MADERA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"), + MADERA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"), + + MADERA_MUX_ROUTES("SPD1TX1", "SPDIF1TX1"), + MADERA_MUX_ROUTES("SPD1TX2", "SPDIF1TX2"), + + MADERA_MIXER_ROUTES("EQ1", "EQ1"), + MADERA_MIXER_ROUTES("EQ2", "EQ2"), + MADERA_MIXER_ROUTES("EQ3", "EQ3"), + MADERA_MIXER_ROUTES("EQ4", "EQ4"), + + MADERA_MIXER_ROUTES("DRC1L", "DRC1L"), + MADERA_MIXER_ROUTES("DRC1R", "DRC1R"), + MADERA_MIXER_ROUTES("DRC2L", "DRC2L"), + MADERA_MIXER_ROUTES("DRC2R", "DRC2R"), + + MADERA_MIXER_ROUTES("LHPF1", "LHPF1"), + MADERA_MIXER_ROUTES("LHPF2", "LHPF2"), + MADERA_MIXER_ROUTES("LHPF3", "LHPF3"), + MADERA_MIXER_ROUTES("LHPF4", "LHPF4"), + + MADERA_MUX_ROUTES("ASRC1IN1L", "ASRC1IN1L"), + MADERA_MUX_ROUTES("ASRC1IN1R", "ASRC1IN1R"), + MADERA_MUX_ROUTES("ASRC1IN2L", "ASRC1IN2L"), + MADERA_MUX_ROUTES("ASRC1IN2R", "ASRC1IN2R"), + MADERA_MUX_ROUTES("ASRC2IN1L", "ASRC2IN1L"), + MADERA_MUX_ROUTES("ASRC2IN1R", "ASRC2IN1R"), + MADERA_MUX_ROUTES("ASRC2IN2L", "ASRC2IN2L"), + MADERA_MUX_ROUTES("ASRC2IN2R", "ASRC2IN2R"), + + MADERA_DSP_ROUTES("DSP1"), + MADERA_DSP_ROUTES("DSP2"), + MADERA_DSP_ROUTES("DSP3"), + MADERA_DSP_ROUTES("DSP4"), + MADERA_DSP_ROUTES("DSP5"), + MADERA_DSP_ROUTES("DSP6"), + MADERA_DSP_ROUTES("DSP7"), + + { "DSP Trigger Out", NULL, "DSP1 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP2 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP3 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP4 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP5 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP6 Trigger Output" }, + { "DSP Trigger Out", NULL, "DSP7 Trigger Output" }, + + { "DSP1 Trigger Output", "Switch", "DSP1" }, + { "DSP2 Trigger Output", "Switch", "DSP2" }, + { "DSP3 Trigger Output", "Switch", "DSP3" }, + { "DSP4 Trigger Output", "Switch", "DSP4" }, + { "DSP5 Trigger Output", "Switch", "DSP5" }, + { "DSP6 Trigger Output", "Switch", "DSP6" }, + { "DSP7 Trigger Output", "Switch", "DSP7" }, + + MADERA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), + MADERA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), + MADERA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), + MADERA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), + + MADERA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), + MADERA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), + MADERA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), + MADERA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), + + MADERA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), + MADERA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), + MADERA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"), + MADERA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"), + + MADERA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), + MADERA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), + MADERA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"), + MADERA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"), + + MADERA_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"), + MADERA_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"), + + MADERA_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"), + MADERA_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"), + + MADERA_MUX_ROUTES("ISRC4INT1", "ISRC4INT1"), + MADERA_MUX_ROUTES("ISRC4INT2", "ISRC4INT2"), + + MADERA_MUX_ROUTES("ISRC4DEC1", "ISRC4DEC1"), + MADERA_MUX_ROUTES("ISRC4DEC2", "ISRC4DEC2"), + + { "AEC1 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC1 Loopback", "HPOUT1R", "OUT1R" }, + { "AEC2 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC2 Loopback", "HPOUT1R", "OUT1R" }, + { "HPOUT1L", NULL, "OUT1L" }, + { "HPOUT1R", NULL, "OUT1R" }, + + { "AEC1 Loopback", "HPOUT2L", "OUT2L" }, + { "AEC1 Loopback", "HPOUT2R", "OUT2R" }, + { "AEC2 Loopback", "HPOUT2L", "OUT2L" }, + { "AEC2 Loopback", "HPOUT2R", "OUT2R" }, + { "HPOUT2L", NULL, "OUT2L" }, + { "HPOUT2R", NULL, "OUT2R" }, + + { "AEC1 Loopback", "HPOUT3L", "OUT3L" }, + { "AEC1 Loopback", "HPOUT3R", "OUT3R" }, + { "AEC2 Loopback", "HPOUT3L", "OUT3L" }, + { "AEC2 Loopback", "HPOUT3R", "OUT3R" }, + { "HPOUT3L", NULL, "OUT3L" }, + { "HPOUT3R", NULL, "OUT3R" }, + + { "AEC1 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC1 Loopback", "SPKDAT1R", "OUT5R" }, + { "AEC2 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC2 Loopback", "SPKDAT1R", "OUT5R" }, + { "SPKDAT1L", NULL, "OUT5L" }, + { "SPKDAT1R", NULL, "OUT5R" }, + + CS47L90_RXANC_INPUT_ROUTES("RXANCL", "RXANCL"), + CS47L90_RXANC_INPUT_ROUTES("RXANCR", "RXANCR"), + + CS47L90_RXANC_OUTPUT_ROUTES("OUT1L", "HPOUT1L"), + CS47L90_RXANC_OUTPUT_ROUTES("OUT1R", "HPOUT1R"), + CS47L90_RXANC_OUTPUT_ROUTES("OUT2L", "HPOUT2L"), + CS47L90_RXANC_OUTPUT_ROUTES("OUT2R", "HPOUT2R"), + CS47L90_RXANC_OUTPUT_ROUTES("OUT3L", "HPOUT3L"), + CS47L90_RXANC_OUTPUT_ROUTES("OUT3R", "HPOUT3R"), + CS47L90_RXANC_OUTPUT_ROUTES("OUT5L", "SPKDAT1L"), + CS47L90_RXANC_OUTPUT_ROUTES("OUT5R", "SPKDAT1R"), + + { "SPDIF1", NULL, "SPD1" }, + + { "MICSUPP", NULL, "SYSCLK" }, + + { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" }, + { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" }, + { "DRC1 Activity Output", "Switch", "DRC1L" }, + { "DRC1 Activity Output", "Switch", "DRC1R" }, + { "DRC2 Activity Output", "Switch", "DRC2L" }, + { "DRC2 Activity Output", "Switch", "DRC2R" }, + + MADERA_MUX_ROUTES("DFC1", "DFC1"), + MADERA_MUX_ROUTES("DFC2", "DFC2"), + MADERA_MUX_ROUTES("DFC3", "DFC3"), + MADERA_MUX_ROUTES("DFC4", "DFC4"), + MADERA_MUX_ROUTES("DFC5", "DFC5"), + MADERA_MUX_ROUTES("DFC6", "DFC6"), + MADERA_MUX_ROUTES("DFC7", "DFC7"), + MADERA_MUX_ROUTES("DFC8", "DFC8"), +}; + +static int cs47l90_set_fll(struct snd_soc_component *component, int fll_id, + int source, unsigned int fref, unsigned int fout) +{ + struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); + + switch (fll_id) { + case MADERA_FLL1_REFCLK: + return madera_set_fll_refclk(&cs47l90->fll[0], source, fref, + fout); + case MADERA_FLL2_REFCLK: + return madera_set_fll_refclk(&cs47l90->fll[1], source, fref, + fout); + case MADERA_FLLAO_REFCLK: + return madera_set_fll_ao_refclk(&cs47l90->fll[2], source, fref, + fout); + case MADERA_FLL1_SYNCCLK: + return madera_set_fll_syncclk(&cs47l90->fll[0], source, fref, + fout); + case MADERA_FLL2_SYNCCLK: + return madera_set_fll_syncclk(&cs47l90->fll[1], source, fref, + fout); + default: + return -EINVAL; + } +} + +static struct snd_soc_dai_driver cs47l90_dai[] = { + { + .name = "cs47l90-aif1", + .id = 1, + .base = MADERA_AIF1_BCLK_CTRL, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l90-aif2", + .id = 2, + .base = MADERA_AIF2_BCLK_CTRL, + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l90-aif3", + .id = 3, + .base = MADERA_AIF3_BCLK_CTRL, + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l90-aif4", + .id = 4, + .base = MADERA_AIF4_BCLK_CTRL, + .playback = { + .stream_name = "AIF4 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF4 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l90-slim1", + .id = 5, + .playback = { + .stream_name = "Slim1 Playback", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim1 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l90-slim2", + .id = 6, + .playback = { + .stream_name = "Slim2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l90-slim3", + .id = 7, + .playback = { + .stream_name = "Slim3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l90-cpu-voicectrl", + .capture = { + .stream_name = "Voice Control CPU", + .channels_min = 1, + .channels_max = 1, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .compress_new = &snd_soc_new_compress, + }, + { + .name = "cs47l90-dsp-voicectrl", + .capture = { + .stream_name = "Voice Control DSP", + .channels_min = 1, + .channels_max = 1, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + }, + { + .name = "cs47l90-cpu-trace", + .capture = { + .stream_name = "Audio Trace CPU", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .compress_new = &snd_soc_new_compress, + }, + { + .name = "cs47l90-dsp-trace", + .capture = { + .stream_name = "Audio Trace DSP", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + }, +}; + +static int cs47l90_open(struct snd_compr_stream *stream) +{ + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, DRV_NAME); + struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l90->core; + struct madera *madera = priv->madera; + int n_adsp; + + if (strcmp(rtd->codec_dai->name, "cs47l90-dsp-voicectrl") == 0) { + n_adsp = 5; + } else if (strcmp(rtd->codec_dai->name, "cs47l90-dsp-trace") == 0) { + n_adsp = 0; + } else { + dev_err(madera->dev, + "No suitable compressed stream for DAI '%s'\n", + rtd->codec_dai->name); + return -EINVAL; + } + + return wm_adsp_compr_open(&priv->adsp[n_adsp], stream); +} + +static irqreturn_t cs47l90_adsp2_irq(int irq, void *data) +{ + struct cs47l90 *cs47l90 = data; + struct madera_priv *priv = &cs47l90->core; + struct madera *madera = priv->madera; + struct madera_voice_trigger_info trig_info; + int serviced = 0; + int i, ret; + + for (i = 0; i < CS47L90_NUM_ADSP; ++i) { + ret = wm_adsp_compr_handle_irq(&priv->adsp[i]); + if (ret != -ENODEV) + serviced++; + if (ret == WM_ADSP_COMPR_VOICE_TRIGGER) { + trig_info.core_num = i + 1; + blocking_notifier_call_chain(&madera->notifier, + MADERA_NOTIFY_VOICE_TRIGGER, + &trig_info); + } + } + + if (!serviced) { + dev_err(madera->dev, "Spurious compressed data IRQ\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +static irqreturn_t cs47l90_dsp_bus_error(int irq, void *data) +{ + struct wm_adsp *dsp = (struct wm_adsp *)data; + + return wm_adsp2_bus_error(dsp); +} + +static int cs47l90_component_probe(struct snd_soc_component *component) +{ + struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l90->core.madera; + int ret, i; + + snd_soc_component_init_regmap(component, madera->regmap); + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = snd_soc_component_get_dapm(component); + mutex_unlock(&madera->dapm_ptr_lock); + + ret = madera_init_inputs(component); + if (ret) + return ret; + + ret = madera_init_outputs(component, CS47L90_MONO_OUTPUTS); + if (ret) + return ret; + + snd_soc_component_disable_pin(component, "HAPTICS"); + + ret = snd_soc_add_component_controls(component, + madera_adsp_rate_controls, + CS47L90_NUM_ADSP); + if (ret) + return ret; + + for (i = 0; i < CS47L90_NUM_ADSP; i++) + wm_adsp2_component_probe(&cs47l90->core.adsp[i], component); + + return 0; +} + +static void cs47l90_component_remove(struct snd_soc_component *component) +{ + struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l90->core.madera; + int i; + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = NULL; + mutex_unlock(&madera->dapm_ptr_lock); + + for (i = 0; i < CS47L90_NUM_ADSP; i++) + wm_adsp2_component_remove(&cs47l90->core.adsp[i], component); +} + +#define CS47L90_DIG_VU 0x0200 + +static unsigned int cs47l90_digital_vu[] = { + MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, + MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, + MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, + MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, +}; + +static const struct snd_compr_ops cs47l90_compr_ops = { + .open = &cs47l90_open, + .free = &wm_adsp_compr_free, + .set_params = &wm_adsp_compr_set_params, + .get_caps = &wm_adsp_compr_get_caps, + .trigger = &wm_adsp_compr_trigger, + .pointer = &wm_adsp_compr_pointer, + .copy = &wm_adsp_compr_copy, +}; + +static const struct snd_soc_component_driver soc_component_dev_cs47l90 = { + .probe = &cs47l90_component_probe, + .remove = &cs47l90_component_remove, + .set_sysclk = &madera_set_sysclk, + .set_pll = &cs47l90_set_fll, + .name = DRV_NAME, + .compr_ops = &cs47l90_compr_ops, + .controls = cs47l90_snd_controls, + .num_controls = ARRAY_SIZE(cs47l90_snd_controls), + .dapm_widgets = cs47l90_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs47l90_dapm_widgets), + .dapm_routes = cs47l90_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs47l90_dapm_routes), + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static int cs47l90_probe(struct platform_device *pdev) +{ + struct madera *madera = dev_get_drvdata(pdev->dev.parent); + struct cs47l90 *cs47l90; + int i, ret; + + BUILD_BUG_ON(ARRAY_SIZE(cs47l90_dai) > MADERA_MAX_DAI); + + /* quick exit if Madera irqchip driver hasn't completed probe */ + if (!madera->irq_dev) { + dev_dbg(&pdev->dev, "irqchip driver not ready\n"); + return -EPROBE_DEFER; + } + + cs47l90 = devm_kzalloc(&pdev->dev, sizeof(struct cs47l90), + GFP_KERNEL); + if (!cs47l90) + return -ENOMEM; + + platform_set_drvdata(pdev, cs47l90); + + cs47l90->core.madera = madera; + cs47l90->core.dev = &pdev->dev; + cs47l90->core.num_inputs = 10; + + ret = madera_core_init(&cs47l90->core); + if (ret) + return ret; + + ret = madera_request_irq(madera, MADERA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", cs47l90_adsp2_irq, + cs47l90); + if (ret != 0) { + dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); + goto error_core; + } + + ret = madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 1); + if (ret) + dev_warn(&pdev->dev, "Failed to set DSP IRQ wake: %d\n", ret); + + for (i = 0; i < CS47L90_NUM_ADSP; i++) { + cs47l90->core.adsp[i].part = "cs47l90"; + cs47l90->core.adsp[i].num = i + 1; + cs47l90->core.adsp[i].type = WMFW_ADSP2; + cs47l90->core.adsp[i].rev = 2; + cs47l90->core.adsp[i].dev = madera->dev; + cs47l90->core.adsp[i].regmap = madera->regmap_32bit; + + cs47l90->core.adsp[i].base = cs47l90_dsp_control_bases[i]; + cs47l90->core.adsp[i].mem = cs47l90_dsp_regions[i]; + cs47l90->core.adsp[i].num_mems = + ARRAY_SIZE(cs47l90_dsp1_regions); + + cs47l90->core.adsp[i].lock_regions = WM_ADSP2_REGION_1_9; + + ret = wm_adsp2_init(&cs47l90->core.adsp[i]); + + if (ret == 0) { + ret = madera_init_bus_error_irq(&cs47l90->core, i, + cs47l90_dsp_bus_error); + if (ret != 0) + wm_adsp2_remove(&cs47l90->core.adsp[i]); + } + + if (ret) { + for (--i; i >= 0; --i) { + madera_free_bus_error_irq(&cs47l90->core, i); + wm_adsp2_remove(&cs47l90->core.adsp[i]); + } + goto error_dsp_irq; + } + } + + madera_init_fll(madera, 1, MADERA_FLL1_CONTROL_1 - 1, + &cs47l90->fll[0]); + madera_init_fll(madera, 2, MADERA_FLL2_CONTROL_1 - 1, + &cs47l90->fll[1]); + madera_init_fll(madera, 4, MADERA_FLLAO_CONTROL_1 - 1, + &cs47l90->fll[2]); + + for (i = 0; i < ARRAY_SIZE(cs47l90_dai); i++) + madera_init_dai(&cs47l90->core, i); + + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(cs47l90_digital_vu); i++) + regmap_update_bits(madera->regmap, cs47l90_digital_vu[i], + CS47L90_DIG_VU, CS47L90_DIG_VU); + + pm_runtime_enable(&pdev->dev); + pm_runtime_idle(&pdev->dev); + + ret = devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_cs47l90, + cs47l90_dai, + ARRAY_SIZE(cs47l90_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register component: %d\n", ret); + goto error_pm_runtime; + } + + return ret; + +error_pm_runtime: + pm_runtime_disable(&pdev->dev); + + for (i = 0; i < CS47L90_NUM_ADSP; i++) { + madera_free_bus_error_irq(&cs47l90->core, i); + wm_adsp2_remove(&cs47l90->core.adsp[i]); + } +error_dsp_irq: + madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(madera, MADERA_IRQ_DSP_IRQ1, cs47l90); +error_core: + madera_core_free(&cs47l90->core); + + return ret; +} + +static int cs47l90_remove(struct platform_device *pdev) +{ + struct cs47l90 *cs47l90 = platform_get_drvdata(pdev); + int i; + + pm_runtime_disable(&pdev->dev); + + for (i = 0; i < CS47L90_NUM_ADSP; i++) { + madera_free_bus_error_irq(&cs47l90->core, i); + wm_adsp2_remove(&cs47l90->core.adsp[i]); + } + + madera_set_irq_wake(cs47l90->core.madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(cs47l90->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l90); + madera_core_free(&cs47l90->core); + + return 0; +} + +static struct platform_driver cs47l90_codec_driver = { + .driver = { + .name = "cs47l90-codec", + }, + .probe = &cs47l90_probe, + .remove = &cs47l90_remove, +}; + +module_platform_driver(cs47l90_codec_driver); + +MODULE_SOFTDEP("pre: madera irq-madera arizona-micsupp"); +MODULE_DESCRIPTION("ASoC CS47L90 driver"); +MODULE_AUTHOR("Nikesh Oswal "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:cs47l90-codec"); From 9e0784d00e35e058353e2e7e59dd956be7519788 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 19 Jun 2019 18:02:13 +0300 Subject: [PATCH 480/626] ASoC: Intel: Skylake: Switch to modern UUID API Switch the driver to use modern UUID API, i.e. guid_t type and accompanying functions, such as guid_equal(). Cc: Liam Girdwood Cc: Mark Brown Cc: Vinod Koul Signed-off-by: Andy Shevchenko Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 12 ++++++------ sound/soc/intel/skylake/skl-sst-dsp.h | 6 +++--- sound/soc/intel/skylake/skl-sst-utils.c | 23 +++++++---------------- sound/soc/intel/skylake/skl-sst.c | 4 +--- sound/soc/intel/skylake/skl-topology.c | 24 ++++++++++++------------ sound/soc/intel/skylake/skl-topology.h | 6 +++--- 6 files changed, 32 insertions(+), 43 deletions(-) diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index edc5ecfc0b55..b00ee2730908 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1319,12 +1319,12 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) { struct skl_sst *ctx = skl->skl_sst; struct skl_module_inst_id *pin_id; - uuid_le *uuid_mod, *uuid_tplg; + guid_t *uuid_mod, *uuid_tplg; struct skl_module *skl_module; struct uuid_module *module; int i, ret = -EIO; - uuid_mod = (uuid_le *)mconfig->guid; + uuid_mod = (guid_t *)mconfig->guid; if (list_empty(&ctx->uuid_list)) { dev_err(ctx->dev, "Module list is empty\n"); @@ -1332,7 +1332,7 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) } list_for_each_entry(module, &ctx->uuid_list, list) { - if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { + if (guid_equal(uuid_mod, &module->uuid)) { mconfig->id.module_id = module->id; if (mconfig->module) mconfig->module->loadable = module->is_loadable; @@ -1349,7 +1349,7 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) for (i = 0; i < skl->nr_modules; i++) { skl_module = skl->modules[i]; uuid_tplg = &skl_module->uuid; - if (!uuid_le_cmp(*uuid_mod, *uuid_tplg)) { + if (guid_equal(uuid_mod, uuid_tplg)) { mconfig->module = skl_module; ret = 0; break; @@ -1361,13 +1361,13 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) list_for_each_entry(module, &ctx->uuid_list, list) { for (i = 0; i < MAX_IN_QUEUE; i++) { pin_id = &mconfig->m_in_pin[i].id; - if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid)) + if (guid_equal(&pin_id->mod_uuid, &module->uuid)) pin_id->module_id = module->id; } for (i = 0; i < MAX_OUT_QUEUE; i++) { pin_id = &mconfig->m_out_pin[i].id; - if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid)) + if (guid_equal(&pin_id->mod_uuid, &module->uuid)) pin_id->module_id = module->id; } } diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index e1d6f6719f7e..cbc7a93d56c2 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -177,7 +177,7 @@ struct skl_dsp_loader_ops { #define MAX_INSTANCE_BUFF 2 struct uuid_module { - uuid_le uuid; + guid_t uuid; int id; int is_loadable; int max_instance; @@ -241,8 +241,8 @@ void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, unsigned int offset, int index); -int skl_get_pvt_id(struct skl_sst *ctx, uuid_le *uuid_mod, int instance_id); -int skl_put_pvt_id(struct skl_sst *ctx, uuid_le *uuid_mod, int *pvt_id); +int skl_get_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int instance_id); +int skl_put_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int *pvt_id); int skl_get_pvt_instance_id_map(struct skl_sst *ctx, int module_id, int instance_id); void skl_freeup_uuid_list(struct skl_sst *ctx); diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 2ae405617876..85551321c35b 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -21,17 +21,11 @@ #include "../common/sst-dsp-priv.h" #include "skl-sst-ipc.h" - -#define UUID_STR_SIZE 37 #define DEFAULT_HASH_SHA256_LEN 32 /* FW Extended Manifest Header id = $AE1 */ #define SKL_EXT_MANIFEST_HEADER_MAGIC 0x31454124 -struct UUID { - u8 id[16]; -}; - union seg_flags { u32 ul; struct { @@ -65,7 +59,7 @@ struct module_type { struct adsp_module_entry { u32 struct_id; u8 name[8]; - struct UUID uuid; + u8 uuid[16]; struct module_type type; u8 hash1[DEFAULT_HASH_SHA256_LEN]; u32 entry_point; @@ -184,13 +178,13 @@ static inline int skl_pvtid_128(struct uuid_module *module) * This generates a 128 bit private unique id for a module TYPE so that * module instance is unique */ -int skl_get_pvt_id(struct skl_sst *ctx, uuid_le *uuid_mod, int instance_id) +int skl_get_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int instance_id) { struct uuid_module *module; int pvt_id; list_for_each_entry(module, &ctx->uuid_list, list) { - if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { + if (guid_equal(uuid_mod, &module->uuid)) { pvt_id = skl_pvtid_128(module); if (pvt_id >= 0) { @@ -214,13 +208,13 @@ EXPORT_SYMBOL_GPL(skl_get_pvt_id); * * This frees a 128 bit private unique id previously generated */ -int skl_put_pvt_id(struct skl_sst *ctx, uuid_le *uuid_mod, int *pvt_id) +int skl_put_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int *pvt_id) { int i; struct uuid_module *module; list_for_each_entry(module, &ctx->uuid_list, list) { - if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { + if (guid_equal(uuid_mod, &module->uuid)) { if (*pvt_id != 0) i = (*pvt_id) / 64; @@ -247,7 +241,6 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, struct adsp_fw_hdr *adsp_hdr; struct adsp_module_entry *mod_entry; int i, num_entry, size; - uuid_le *uuid_bin; const char *buf; struct skl_sst *skl = ctx->thread_context; struct uuid_module *module; @@ -279,8 +272,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, return -EINVAL; } - mod_entry = (struct adsp_module_entry *) - (buf + offset + adsp_hdr->len); + mod_entry = (struct adsp_module_entry *)(buf + offset + adsp_hdr->len); num_entry = adsp_hdr->num_modules; @@ -307,8 +299,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, goto free_uuid_list; } - uuid_bin = (uuid_le *)mod_entry->uuid.id; - memcpy(&module->uuid, uuid_bin, sizeof(module->uuid)); + guid_copy(&module->uuid, (guid_t *)&mod_entry->uuid); module->id = (i | (index << 12)); module->is_loadable = mod_entry->type.load_type; diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 5951bbdf1f1a..13c636dece56 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -420,11 +420,9 @@ static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid) struct skl_module_table *module_entry = NULL; int ret = 0; char mod_name[64]; /* guid str = 32 chars + 4 hyphens */ - uuid_le *uuid_mod; - uuid_mod = (uuid_le *)guid; snprintf(mod_name, sizeof(mod_name), "%s%pUL%s", - "intel/dsp_fw_", uuid_mod, ".bin"); + "intel/dsp_fw_", guid, ".bin"); module_entry = skl_module_get_from_id(ctx, mod_id); if (module_entry == NULL) { diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index c69d999d7bf1..9fd756bcc740 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -580,7 +580,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) int ret = 0; list_for_each_entry(w_module, &pipe->w_list, node) { - uuid_le *uuid_mod; + guid_t *uuid_mod; w = w_module->w; mconfig = w->priv; @@ -588,7 +588,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) if (mconfig->id.module_id < 0) { dev_err(skl->skl_sst->dev, "module %pUL id not populated\n", - (uuid_le *)mconfig->guid); + (guid_t *)mconfig->guid); return -EIO; } @@ -622,7 +622,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) * FE/BE params */ skl_tplg_update_module_params(w, ctx); - uuid_mod = (uuid_le *)mconfig->guid; + uuid_mod = (guid_t *)mconfig->guid; mconfig->id.pvt_id = skl_get_pvt_id(ctx, uuid_mod, mconfig->id.instance_id); if (mconfig->id.pvt_id < 0) @@ -661,9 +661,9 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, struct skl_module_cfg *mconfig = NULL; list_for_each_entry(w_module, &pipe->w_list, node) { - uuid_le *uuid_mod; + guid_t *uuid_mod; mconfig = w_module->w->priv; - uuid_mod = (uuid_le *)mconfig->guid; + uuid_mod = (guid_t *)mconfig->guid; if (mconfig->module->loadable && ctx->dsp->fw_ops.unload_mod && mconfig->m_state > SKL_MODULE_UNINIT) { @@ -918,12 +918,12 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, return 0; } -static int skl_get_module_id(struct skl_sst *ctx, uuid_le *uuid) +static int skl_get_module_id(struct skl_sst *ctx, guid_t *uuid) { struct uuid_module *module; list_for_each_entry(module, &ctx->uuid_list, list) { - if (uuid_le_cmp(*uuid, module->uuid) == 0) + if (guid_equal(uuid, &module->uuid)) return module->id; } @@ -2121,11 +2121,11 @@ static int skl_tplg_add_pipe(struct device *dev, return 0; } -static int skl_tplg_get_uuid(struct device *dev, u8 *guid, +static int skl_tplg_get_uuid(struct device *dev, guid_t *guid, struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) { if (uuid_tkn->token == SKL_TKN_UUID) { - memcpy(guid, &uuid_tkn->uuid, 16); + guid_copy(guid, (guid_t *)&uuid_tkn->uuid); return 0; } @@ -2151,7 +2151,7 @@ static int skl_tplg_fill_pin(struct device *dev, break; case SKL_TKN_UUID: - ret = skl_tplg_get_uuid(dev, m_pin[pin_index].id.mod_uuid.b, + ret = skl_tplg_get_uuid(dev, &m_pin[pin_index].id.mod_uuid, (struct snd_soc_tplg_vendor_uuid_elem *)tkn_elem); if (ret < 0) return ret; @@ -2667,7 +2667,7 @@ static int skl_tplg_get_tokens(struct device *dev, case SND_SOC_TPLG_TUPLE_TYPE_UUID: if (is_module_guid) { - ret = skl_tplg_get_uuid(dev, mconfig->guid, + ret = skl_tplg_get_uuid(dev, (guid_t *)mconfig->guid, array->uuid); is_module_guid = false; } else { @@ -3486,7 +3486,7 @@ static int skl_tplg_get_manifest_uuid(struct device *dev, if (uuid_tkn->token == SKL_TKN_UUID) { mod = skl->modules[ref_count]; - memcpy(&mod->uuid, &uuid_tkn->uuid, sizeof(uuid_tkn->uuid)); + guid_copy(&mod->uuid, (guid_t *)&uuid_tkn->uuid); ref_count++; } else { dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 82282cac9751..9311e248b6f9 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -224,7 +224,7 @@ struct skl_mod_inst_map { struct skl_uuid_inst_map { u16 inst_id; u16 reserved; - uuid_le mod_uuid; + guid_t mod_uuid; } __packed; struct skl_kpb_params { @@ -236,7 +236,7 @@ struct skl_kpb_params { }; struct skl_module_inst_id { - uuid_le mod_uuid; + guid_t mod_uuid; int module_id; u32 instance_id; int pvt_id; @@ -369,7 +369,7 @@ struct skl_module_res { }; struct skl_module { - uuid_le uuid; + guid_t uuid; u8 loadable; u8 input_pin_type; u8 output_pin_type; From 5dd17a3c3ed545f73b8bf7754efd5f6125bf7531 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Jun 2019 12:20:01 +0300 Subject: [PATCH 481/626] ASoC: ti: davinci-mcasp: Set unused serializers as INACTIVE Unused serializers needs to be configured as INACTIVE, otherwise they will underflow/overflow when multiple serializers are connected, but some are not needed for the given stream. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index a8378d223a9e..8bec0dc4f754 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -848,14 +848,15 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, rx_ser < max_active_serializers) { clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); rx_ser++; - } else if (mcasp->serial_dir[i] == INACTIVE_MODE) { + } else { + /* Inactive or unused pin, set it to inactive */ mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), SRMOD_INACTIVE, SRMOD_MASK); - clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); - } else if (mcasp->serial_dir[i] == TX_MODE) { - /* Unused TX pins, clear PDIR */ - mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - mcasp->dismod, DISMOD_MASK); + /* If unused, set DISMOD for the pin */ + if (mcasp->serial_dir[i] != INACTIVE_MODE) + mcasp_mod_bits(mcasp, + DAVINCI_MCASP_XRSRCTL_REG(i), + mcasp->dismod, DISMOD_MASK); clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); } } @@ -965,6 +966,7 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream, for (i = 0; i < active_slots; i++) mask |= (1 << i); } + mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); if (!mcasp->dat_port) From fd14f4436fd47d5418023c90e933e66d3645552e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Jun 2019 12:20:02 +0300 Subject: [PATCH 482/626] ASoC: ti: davinci-mcasp: Fix slot mask settings when using multiple AXRs If multiple serializers are connected in the system and the number of channels will need to use more than one serializer the mask to enable the serializers were left to 0 if tdm_mask is provided Fixes: dd55ff8346a97 ("ASoC: davinci-mcasp: Add set_tdm_slots() support") Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 8bec0dc4f754..62222915d632 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -946,14 +946,13 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream, active_slots = hweight32(mcasp->tdm_mask[stream]); active_serializers = (channels + active_slots - 1) / active_slots; - if (active_serializers == 1) { + if (active_serializers == 1) active_slots = channels; - for (i = 0; i < total_slots; i++) { - if ((1 << i) & mcasp->tdm_mask[stream]) { - mask |= (1 << i); - if (--active_slots <= 0) - break; - } + for (i = 0; i < total_slots; i++) { + if ((1 << i) & mcasp->tdm_mask[stream]) { + mask |= (1 << i); + if (--active_slots <= 0) + break; } } } else { From b5d8dffb8cc9792c3bb4310e142932c8bc5c0387 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Jun 2019 12:26:55 +0300 Subject: [PATCH 483/626] ASoC: pcm3168a: Rename min_frame_size to slot_width It represents slot size and not frame. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 9eb24ca09793..e1658947090b 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -435,7 +435,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, u32 val, mask, shift, reg; unsigned int rate, fmt, ratio, max_ratio; unsigned int chan; - int i, min_frame_size; + int i, slot_width; rate = params_rate(params); chan = params_channels(params); @@ -470,11 +470,11 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, } if (pcm3168a->slot_width) - min_frame_size = pcm3168a->slot_width; + slot_width = pcm3168a->slot_width; else - min_frame_size = params_width(params); + slot_width = params_width(params); - switch (min_frame_size) { + switch (slot_width) { case 16: if (master_mode || (fmt != PCM3168A_FMT_RIGHT_J)) { dev_err(component->dev, "16-bit slots are supported only for slave mode using right justified\n"); @@ -491,7 +491,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, case 32: break; default: - dev_err(component->dev, "unsupported frame size: %d\n", min_frame_size); + dev_err(component->dev, "unsupported frame size: %d\n", slot_width); return -EINVAL; } From 9700022109b6c495fb571f77324d34b294b29145 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Jun 2019 12:26:56 +0300 Subject: [PATCH 484/626] ASoC: pcm3168a: Add support for multi DIN/DOUT with TDM slots parameter The driver was wired to be only usable in DIN1/DOUT1 mode, switching between TDM and non TDM modes based on the number of channels. While keeping this functionality for compatibility add support for using all DIN1/2/3/4 and DOUT1/2/3 if it is needed by setting the TDM slots to 2. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index e1658947090b..d4e372182c55 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -411,9 +411,11 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, return -EINVAL; } - pcm3168a->tdm_slots = slots; - pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; - pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; + if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) { + dev_err(component->dev, "Not matching slots %d vs %d\n", + pcm3168a->tdm_slots, slots); + return -EINVAL; + } if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) { dev_err(component->dev, "Not matching slot_width %d vs %d\n", @@ -421,7 +423,11 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, return -EINVAL; } + pcm3168a->tdm_slots = slots; pcm3168a->slot_width = slot_width; + pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; + pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; + return 0; } @@ -434,11 +440,10 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, bool tx, master_mode; u32 val, mask, shift, reg; unsigned int rate, fmt, ratio, max_ratio; - unsigned int chan; + unsigned int tdm_slots; int i, slot_width; rate = params_rate(params); - chan = params_channels(params); ratio = pcm3168a->sysclk / rate; @@ -495,8 +500,20 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - /* for TDM */ - if (chan > 2) { + if (pcm3168a->tdm_slots) + tdm_slots = pcm3168a->tdm_slots; + else + tdm_slots = params_channels(params); + + /* + * Switch the codec to TDM mode when more than 2 TDM slots are needed + * for the stream. + * If pcm3168a->tdm_slots is not set or set to more than 2 (8/6 usually) + * then DIN1/DOUT1 is used in TDM mode. + * If pcm3168a->tdm_slots is set to 2 then DIN1/2/3/4 and DOUT1/2/3 is + * used in normal mode, no need to switch to TDM modes. + */ + if (tdm_slots > 2) { switch (fmt) { case PCM3168A_FMT_I2S: case PCM3168A_FMT_DSP_A: From 7f80e1376aa4e74924ca3cb229dbd6c54fa4656e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 20 Jun 2019 16:03:41 +0900 Subject: [PATCH 485/626] ASoC: rt5514-spi: don't use snd_soc_lookup_component() rt5514-spi can use dev_get_drvdata() to get its component because it is using snd_soc_component_set_drvdata(); static int rt5514_spi_pcm_probe(...) { ... => snd_soc_component_set_drvdata(component, ...); ... } We don't need to use snd_soc_lookup_component() for it. This patch uses dev_get_drvdata() instead of snd_soc_lookup_component(). Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/rt5514-spi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index bec2eefa8b0f..862fad41b26a 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -473,9 +473,7 @@ static int __maybe_unused rt5514_suspend(struct device *dev) static int __maybe_unused rt5514_resume(struct device *dev) { - struct snd_soc_component *component = snd_soc_lookup_component(dev, DRV_NAME); - struct rt5514_dsp *rt5514_dsp = - snd_soc_component_get_drvdata(component); + struct rt5514_dsp *rt5514_dsp = dev_get_drvdata(dev); int irq = to_spi_device(dev)->irq; u8 buf[8]; From 9628fc82f9feedfcb6b9756efb2966c00b3811ef Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 18 Jun 2019 22:26:15 +0900 Subject: [PATCH 486/626] ALSA: firewire-tascam: unify stop and release method for duplex streams >From callbacks for pcm and rawmidi interfaces, the functions to stop and release duplex streams are called at the same time. This commit merges the two functions. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-pcm.c | 1 - sound/firewire/tascam/tascam-stream.c | 14 +++++--------- sound/firewire/tascam/tascam.h | 1 - 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 450711bef508..300683a82c68 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -118,7 +118,6 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) --tscm->substreams_counter; snd_tscm_stream_stop_duplex(tscm); - snd_tscm_stream_release_duplex(tscm); mutex_unlock(&tscm->mutex); diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index f572dfc15114..0e515b7be276 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -380,14 +380,6 @@ int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) return 0; } -void snd_tscm_stream_release_duplex(struct snd_tscm *tscm) -{ - if (tscm->substreams_counter == 0) { - fw_iso_resources_free(&tscm->tx_resources); - fw_iso_resources_free(&tscm->rx_resources); - } -} - int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) { unsigned int generation = tscm->rx_resources.generation; @@ -455,8 +447,12 @@ error: void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) { - if (tscm->substreams_counter == 0) + if (tscm->substreams_counter == 0) { finish_session(tscm); + + fw_iso_resources_free(&tscm->tx_resources); + fw_iso_resources_free(&tscm->rx_resources); + } } void snd_tscm_stream_lock_changed(struct snd_tscm *tscm) diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 1cb75c374f11..4ed88cceaedb 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -148,7 +148,6 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm); void snd_tscm_stream_update_duplex(struct snd_tscm *tscm); void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm); int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate); -void snd_tscm_stream_release_duplex(struct snd_tscm *tscm); int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate); void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm); From af26bacc1c5ace50645b29aea148c6143753edd4 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 18 Jun 2019 22:26:16 +0900 Subject: [PATCH 487/626] ALSA: fireface: unify stop and release method for duplex streams >From callbacks for pcm and rawmidi interfaces, the functions to stop and release duplex streams are called at the same time. This commit merges the two functions. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-pcm.c | 1 - sound/firewire/fireface/ff-stream.c | 14 +++++--------- sound/firewire/fireface/ff.h | 1 - 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index 938985c2d4a8..75228e769687 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -233,7 +233,6 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) --ff->substreams_counter; snd_ff_stream_stop_duplex(ff); - snd_ff_stream_release_duplex(ff); mutex_unlock(&ff->mutex); diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 884705ecf940..049920a6d43e 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -149,14 +149,6 @@ int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate) return 0; } -void snd_ff_stream_release_duplex(struct snd_ff *ff) -{ - if (ff->substreams_counter == 0) { - fw_iso_resources_free(&ff->tx_resources); - fw_iso_resources_free(&ff->rx_resources); - } -} - int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) { int err; @@ -217,8 +209,12 @@ error: void snd_ff_stream_stop_duplex(struct snd_ff *ff) { - if (ff->substreams_counter == 0) + if (ff->substreams_counter == 0) { finish_session(ff); + + fw_iso_resources_free(&ff->tx_resources); + fw_iso_resources_free(&ff->rx_resources); + } } void snd_ff_stream_update_duplex(struct snd_ff *ff) diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index fe5739ee1c88..9b52c368f6de 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -139,7 +139,6 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, int snd_ff_stream_init_duplex(struct snd_ff *ff); void snd_ff_stream_destroy_duplex(struct snd_ff *ff); int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate); -void snd_ff_stream_release_duplex(struct snd_ff *ff); int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate); void snd_ff_stream_stop_duplex(struct snd_ff *ff); void snd_ff_stream_update_duplex(struct snd_ff *ff); From eccd895c998549ebb4a80f0ebee13b6a179bd40c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 18 Jun 2019 22:26:17 +0900 Subject: [PATCH 488/626] ALSA: firewire-motu: unify stop and release method for duplex streams >From callbacks for pcm and rawmidi interfaces, the functions to stop and release duplex streams are called at the same time. This commit merges the two functions. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-midi.c | 1 - sound/firewire/motu/motu-pcm.c | 1 - sound/firewire/motu/motu-stream.c | 14 +++++--------- sound/firewire/motu/motu.h | 1 - 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/sound/firewire/motu/motu-midi.c b/sound/firewire/motu/motu-midi.c index a463730c72bc..4520c0060b83 100644 --- a/sound/firewire/motu/motu-midi.c +++ b/sound/firewire/motu/motu-midi.c @@ -40,7 +40,6 @@ static int midi_close(struct snd_rawmidi_substream *substream) --motu->substreams_counter; snd_motu_stream_stop_duplex(motu); - snd_motu_stream_release_duplex(motu); mutex_unlock(&motu->mutex); diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index b9852c911b98..60c691d18952 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -224,7 +224,6 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) --motu->substreams_counter; snd_motu_stream_stop_duplex(motu); - snd_motu_stream_release_duplex(motu); mutex_unlock(&motu->mutex); diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 82891583b736..8aab5db71c0f 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -200,14 +200,6 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate) return 0; } -void snd_motu_stream_release_duplex(struct snd_motu *motu) -{ - if (motu->substreams_counter == 0) { - fw_iso_resources_free(&motu->tx_resources); - fw_iso_resources_free(&motu->rx_resources); - } -} - static int ensure_packet_formats(struct snd_motu *motu) { __be32 reg; @@ -301,8 +293,12 @@ stop_streams: void snd_motu_stream_stop_duplex(struct snd_motu *motu) { - if (motu->substreams_counter == 0) + if (motu->substreams_counter == 0) { finish_session(motu); + + fw_iso_resources_free(&motu->tx_resources); + fw_iso_resources_free(&motu->rx_resources); + } } static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir) diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 32cd42873fd0..a4ac320f2c9e 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -154,7 +154,6 @@ int snd_motu_stream_init_duplex(struct snd_motu *motu); void snd_motu_stream_destroy_duplex(struct snd_motu *motu); int snd_motu_stream_cache_packet_formats(struct snd_motu *motu); int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate); -void snd_motu_stream_release_duplex(struct snd_motu *motu); int snd_motu_stream_start_duplex(struct snd_motu *motu); void snd_motu_stream_stop_duplex(struct snd_motu *motu); int snd_motu_stream_lock_try(struct snd_motu *motu); From b9434540dd8f702c2cf33b82674e027cb779146e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 18 Jun 2019 22:26:18 +0900 Subject: [PATCH 489/626] ALSA: firewire-digi00x: unify stop and release method for duplex streams >From callbacks for pcm and rawmidi interfaces, the functions to stop and release duplex streams are called at the same time. This commit merges the two functions. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-midi.c | 1 - sound/firewire/digi00x/digi00x-pcm.c | 1 - sound/firewire/digi00x/digi00x-stream.c | 14 +++++--------- sound/firewire/digi00x/digi00x.h | 1 - 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-midi.c b/sound/firewire/digi00x/digi00x-midi.c index cca888cce0d3..ca06ad318ed6 100644 --- a/sound/firewire/digi00x/digi00x-midi.c +++ b/sound/firewire/digi00x/digi00x-midi.c @@ -37,7 +37,6 @@ static int midi_close(struct snd_rawmidi_substream *substream) mutex_lock(&dg00x->mutex); --dg00x->substreams_counter; snd_dg00x_stream_stop_duplex(dg00x); - snd_dg00x_stream_release_duplex(dg00x); mutex_unlock(&dg00x->mutex); snd_dg00x_stream_lock_release(dg00x); diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index 9ed2ebdcf23a..c38fbd6ded9f 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -189,7 +189,6 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) --dg00x->substreams_counter; snd_dg00x_stream_stop_duplex(dg00x); - snd_dg00x_stream_release_duplex(dg00x); mutex_unlock(&dg00x->mutex); diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 3c5e1c5a2e11..7c8e7ad48d03 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -293,14 +293,6 @@ int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate) return 0; } -void snd_dg00x_stream_release_duplex(struct snd_dg00x *dg00x) -{ - if (dg00x->substreams_counter == 0) { - fw_iso_resources_free(&dg00x->tx_resources); - fw_iso_resources_free(&dg00x->rx_resources); - } -} - int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) { unsigned int generation = dg00x->rx_resources.generation; @@ -372,8 +364,12 @@ error: void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x) { - if (dg00x->substreams_counter == 0) + if (dg00x->substreams_counter == 0) { finish_session(dg00x); + + fw_iso_resources_free(&dg00x->tx_resources); + fw_iso_resources_free(&dg00x->rx_resources); + } } void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x) diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 3fb1c49f6f9e..2d026b5b0079 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h @@ -143,7 +143,6 @@ int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x); int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate); int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x); void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x); -void snd_dg00x_stream_release_duplex(struct snd_dg00x *dg00x); void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x); void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x); From 740680f22d96e078245211b40fc2c141a24c8d1a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 18 Jun 2019 22:26:19 +0900 Subject: [PATCH 490/626] ALSA: dice: unify stop and release method for duplex streams >From callbacks for pcm and rawmidi interfaces, the functions to stop and release duplex streams are called at the same time. This commit merges the two functions. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-midi.c | 1 - sound/firewire/dice/dice-pcm.c | 1 - sound/firewire/dice/dice-stream.c | 8 ++------ sound/firewire/dice/dice.h | 1 - 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c index 6172dad87c4e..436f0c3c0fbb 100644 --- a/sound/firewire/dice/dice-midi.c +++ b/sound/firewire/dice/dice-midi.c @@ -40,7 +40,6 @@ static int midi_close(struct snd_rawmidi_substream *substream) --dice->substreams_counter; snd_dice_stream_stop_duplex(dice); - snd_dice_stream_release_duplex(dice); mutex_unlock(&dice->mutex); diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 00b55dfc3b2c..8368073f7fa0 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -265,7 +265,6 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) --dice->substreams_counter; snd_dice_stream_stop_duplex(dice); - snd_dice_stream_release_duplex(dice); mutex_unlock(&dice->mutex); diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index e9e5c5fffb70..433714a117a0 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -336,12 +336,6 @@ error: return err; } -void snd_dice_stream_release_duplex(struct snd_dice *dice) -{ - if (dice->substreams_counter == 0) - release_resources(dice); -} - static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, unsigned int rate, struct reg_params *params) { @@ -494,6 +488,8 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice) if (dice->substreams_counter == 0) { if (get_register_params(dice, &tx_params, &rx_params) >= 0) finish_session(dice, &tx_params, &rx_params); + + release_resources(dice); } } diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index f95073b85010..fd3f483283d5 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -210,7 +210,6 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice); int snd_dice_stream_init_duplex(struct snd_dice *dice); void snd_dice_stream_destroy_duplex(struct snd_dice *dice); int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate); -void snd_dice_stream_release_duplex(struct snd_dice *dice); void snd_dice_stream_update_duplex(struct snd_dice *dice); int snd_dice_stream_detect_current_formats(struct snd_dice *dice); From 7599e279c04511731e2aba4a6dc7b98e5c2a2d25 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 18 Jun 2019 22:26:20 +0900 Subject: [PATCH 491/626] ALSA: bebob: ensure to release isochronous resources in pcm.hw_params callback When stopping packet streaming in reserve function for duplex streams, isochronous resources should be released. Fixes: 7bc93821a70a ("ALSA: firewire-lib: split allocation of isochronous resources from establishment of connection") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_stream.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 1070a675179d..63e78fc8711d 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -571,6 +571,9 @@ int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) amdtp_stream_stop(&bebob->rx_stream); break_both_connections(bebob); + + cmp_connection_release(&bebob->out_conn); + cmp_connection_release(&bebob->in_conn); } if (bebob->substreams_counter == 0 || curr_rate != rate) { From a9679dd31dd379e7e14a13c55bd0a3214c18fe47 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 18 Jun 2019 22:26:21 +0900 Subject: [PATCH 492/626] ALSA: fireworks: ensure to release isochronous resources in pcm.hw_params callback When stopping packet streaming in reserve function for duplex streams, isochronous resources should be released. Fixes: 7bc93821a70a ("ALSA: firewire-lib: split allocation of isochronous resources from establishment of connection") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_stream.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 81c1bb209a89..16cf635a6f57 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -217,6 +217,9 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) if (rate != curr_rate) { stop_stream(efw, &efw->tx_stream); stop_stream(efw, &efw->rx_stream); + + cmp_connection_release(&efw->out_conn); + cmp_connection_release(&efw->in_conn); } if (efw->substreams_counter == 0 || rate != curr_rate) { From 3f2ce83ddba936568de2d057bbd29d74cd2de80d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 18 Jun 2019 22:26:22 +0900 Subject: [PATCH 493/626] ALSA: oxfw: ensure to release isochronous resources in pcm.hw_params callback When stopping packet streaming in reserve function for duplex streams, isochronous resources should be released. Fixes: 7bc93821a70a ("ALSA: firewire-lib: split allocation of isochronous resources from establishment of connection") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-stream.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index a8bc798731ff..a7502810a3ad 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -283,10 +283,12 @@ int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, if (formation.rate != rate || formation.pcm != pcm_channels) { amdtp_stream_stop(&oxfw->rx_stream); cmp_connection_break(&oxfw->in_conn); + cmp_connection_release(&oxfw->in_conn); if (oxfw->has_output) { amdtp_stream_stop(&oxfw->tx_stream); cmp_connection_break(&oxfw->out_conn); + cmp_connection_release(&oxfw->out_conn); } } From eee22af1eddedf2a140fcf6855564420abed818d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 24 Jun 2019 18:20:15 +0900 Subject: [PATCH 494/626] Revert "ALSA: firewire-lib: fix inverted node IDs for amdtp_packet events" This reverts commit e703965a129cdd72ff74e248f8fbf0d617844527. When creating this patch, I compared the value of src field to the value of first byte of cip_header field (SID) in tracing event. But in this test I used a device which has a quirk to transfer isochronous packet with invalid SID. The original change is valid. Fixes: e703965a129c ("ALSA: firewire-lib: fix inverted node IDs for amdtp_packet events") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream-trace.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index 5fe0920f04e5..ab708857979f 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -35,11 +35,11 @@ TRACE_EVENT(amdtp_packet, __entry->cycle = cycles % CYCLES_PER_SECOND; __entry->channel = s->context->channel; if (s->direction == AMDTP_IN_STREAM) { - __entry->src = fw_parent_device(s->unit)->card->node_id; - __entry->dest = fw_parent_device(s->unit)->node_id; - } else { __entry->src = fw_parent_device(s->unit)->node_id; __entry->dest = fw_parent_device(s->unit)->card->node_id; + } else { + __entry->src = fw_parent_device(s->unit)->card->node_id; + __entry->dest = fw_parent_device(s->unit)->node_id; } if (cip_header) { memcpy(__get_dynamic_array(cip_header), cip_header, From c5dfd4b885284e4eaaf66172b918894fdde7eb06 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 24 Jun 2019 18:16:46 +0900 Subject: [PATCH 495/626] ALSA: firewire-motu: unify common tracepoints for both direction In ALSA firewire-motu driver, some tracepoints are supported to probe vendor-specific data fields for SPH and status/control messages in payload of isochronous packet. At present, the events of tracepoints are unique each of direction, however the pair of events has the same structure and print format. It's possible to unify the pair. This commit unifies the pair. From userspace, direction is specified by filtering for src/dst fields in the structure. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/amdtp-motu-trace.h | 70 ++++++-------------------- sound/firewire/motu/amdtp-motu.c | 8 +-- 2 files changed, 20 insertions(+), 58 deletions(-) diff --git a/sound/firewire/motu/amdtp-motu-trace.h b/sound/firewire/motu/amdtp-motu-trace.h index cd0cbfa9f96f..edc551d4ca50 100644 --- a/sound/firewire/motu/amdtp-motu-trace.h +++ b/sound/firewire/motu/amdtp-motu-trace.h @@ -18,7 +18,7 @@ static void copy_sph(u32 *frame, __be32 *buffer, unsigned int data_blocks, static void copy_message(u64 *frames, __be32 *buffer, unsigned int data_blocks, unsigned int data_block_quadlets); -TRACE_EVENT(in_data_block_sph, +TRACE_EVENT(data_block_sph, TP_PROTO(struct amdtp_stream *s, unsigned int data_blocks, __be32 *buffer), TP_ARGS(s, data_blocks, buffer), TP_STRUCT__entry( @@ -28,8 +28,13 @@ TRACE_EVENT(in_data_block_sph, __dynamic_array(u32, tstamps, data_blocks) ), TP_fast_assign( - __entry->src = fw_parent_device(s->unit)->node_id; - __entry->dst = fw_parent_device(s->unit)->card->node_id; + if (s->direction == AMDTP_IN_STREAM) { + __entry->src = fw_parent_device(s->unit)->node_id; + __entry->dst = fw_parent_device(s->unit)->card->node_id; + } else { + __entry->src = fw_parent_device(s->unit)->card->node_id; + __entry->dst = fw_parent_device(s->unit)->node_id; + } __entry->data_blocks = data_blocks; copy_sph(__get_dynamic_array(tstamps), buffer, data_blocks, s->data_block_quadlets); ), @@ -42,31 +47,7 @@ TRACE_EVENT(in_data_block_sph, ) ); -TRACE_EVENT(out_data_block_sph, - TP_PROTO(struct amdtp_stream *s, unsigned int data_blocks, __be32 *buffer), - TP_ARGS(s, data_blocks, buffer), - TP_STRUCT__entry( - __field(int, src) - __field(int, dst) - __field(unsigned int, data_blocks) - __dynamic_array(u32, tstamps, data_blocks) - ), - TP_fast_assign( - __entry->src = fw_parent_device(s->unit)->card->node_id; - __entry->dst = fw_parent_device(s->unit)->node_id; - __entry->data_blocks = data_blocks; - copy_sph(__get_dynamic_array(tstamps), buffer, data_blocks, s->data_block_quadlets); - ), - TP_printk( - "%04x %04x %u %s", - __entry->src, - __entry->dst, - __entry->data_blocks, - __print_array(__get_dynamic_array(tstamps), __entry->data_blocks, 4) - ) -); - -TRACE_EVENT(in_data_block_message, +TRACE_EVENT(data_block_message, TP_PROTO(struct amdtp_stream *s, unsigned int data_blocks, __be32 *buffer), TP_ARGS(s, data_blocks, buffer), TP_STRUCT__entry( @@ -76,32 +57,13 @@ TRACE_EVENT(in_data_block_message, __dynamic_array(u64, messages, data_blocks) ), TP_fast_assign( - __entry->src = fw_parent_device(s->unit)->node_id; - __entry->dst = fw_parent_device(s->unit)->card->node_id; - __entry->data_blocks = data_blocks; - copy_message(__get_dynamic_array(messages), buffer, data_blocks, s->data_block_quadlets); - ), - TP_printk( - "%04x %04x %u %s", - __entry->src, - __entry->dst, - __entry->data_blocks, - __print_array(__get_dynamic_array(messages), __entry->data_blocks, 8) - ) -); - -TRACE_EVENT(out_data_block_message, - TP_PROTO(struct amdtp_stream *s, unsigned int data_blocks, __be32 *buffer), - TP_ARGS(s, data_blocks, buffer), - TP_STRUCT__entry( - __field(int, src) - __field(int, dst) - __field(unsigned int, data_blocks) - __dynamic_array(u64, messages, data_blocks) - ), - TP_fast_assign( - __entry->src = fw_parent_device(s->unit)->card->node_id; - __entry->dst = fw_parent_device(s->unit)->node_id; + if (s->direction == AMDTP_IN_STREAM) { + __entry->src = fw_parent_device(s->unit)->node_id; + __entry->dst = fw_parent_device(s->unit)->card->node_id; + } else { + __entry->src = fw_parent_device(s->unit)->card->node_id; + __entry->dst = fw_parent_device(s->unit)->node_id; + } __entry->data_blocks = data_blocks; copy_message(__get_dynamic_array(messages), buffer, data_blocks, s->data_block_quadlets); ), diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 62685f2528ce..1c9ce04a2e89 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -306,8 +306,8 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, struct amdtp_motu *p = s->protocol; struct snd_pcm_substream *pcm; - trace_in_data_block_sph(s, data_blocks, buffer); - trace_in_data_block_message(s, data_blocks, buffer); + trace_data_block_sph(s, data_blocks, buffer); + trace_data_block_message(s, data_blocks, buffer); if (p->midi_ports) read_midi_messages(s, buffer, data_blocks); @@ -384,8 +384,8 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, write_sph(s, buffer, data_blocks); - trace_out_data_block_sph(s, data_blocks, buffer); - trace_out_data_block_message(s, data_blocks, buffer); + trace_data_block_sph(s, data_blocks, buffer); + trace_data_block_message(s, data_blocks, buffer); return data_blocks; } From 801ebf1043ae7b182588554cc9b9ad3c14bc2ab5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 24 Jun 2019 15:08:28 +0200 Subject: [PATCH 496/626] ALSA: usb-audio: Sanity checks for each pipe and EP types The recent USB core code performs sanity checks for the given pipe and EP types, and it can be hit by manipulated USB descriptors by syzbot. For making syzbot happier, this patch introduces a local helper for a sanity check in the driver side and calls it at each place before the message handling, so that we can avoid the WARNING splats. Reported-by: syzbot+d952e5e28f5fb7718d23@syzkaller.appspotmail.com Signed-off-by: Takashi Iwai --- sound/usb/helper.c | 17 +++++++++++++++++ sound/usb/helper.h | 1 + sound/usb/quirks.c | 18 +++++++++++++++--- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/sound/usb/helper.c b/sound/usb/helper.c index 7712e2b84183..b1cc9499c57e 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c @@ -76,6 +76,20 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype return NULL; } +/* check the validity of pipe and EP types */ +int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe) +{ + static const int pipetypes[4] = { + PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT + }; + struct usb_host_endpoint *ep; + + ep = usb_pipe_endpoint(dev, pipe); + if (usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)]) + return -EINVAL; + return 0; +} + /* * Wrapper for usb_control_msg(). * Allocates a temp buffer to prevent dmaing from/to the stack. @@ -88,6 +102,9 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, void *buf = NULL; int timeout; + if (snd_usb_pipe_sanity_check(dev, pipe)) + return -EINVAL; + if (size > 0) { buf = kmemdup(data, size, GFP_KERNEL); if (!buf) diff --git a/sound/usb/helper.h b/sound/usb/helper.h index d338bd0e0ca6..6afb70156ec4 100644 --- a/sound/usb/helper.h +++ b/sound/usb/helper.h @@ -7,6 +7,7 @@ unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size); void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype); void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsubtype); +int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe); int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size); diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index e6ce1bbe6ca6..057143330a28 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -840,11 +840,13 @@ static int snd_usb_novation_boot_quirk(struct usb_device *dev) static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev) { int err, actual_length; - /* "midi send" enable */ static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 }; + void *buf; - void *buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL); + if (snd_usb_pipe_sanity_check(dev, usb_sndintpipe(dev, 0x05))) + return -EINVAL; + buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL); if (!buf) return -ENOMEM; err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), buf, @@ -869,7 +871,11 @@ static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev) static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev) { - int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + int ret; + + if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0))) + return -EINVAL; + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 0, NULL, 0, 1000); @@ -976,6 +982,8 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) dev_dbg(&dev->dev, "Waiting for Axe-Fx III to boot up...\n"); + if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0))) + return -EINVAL; /* If the Axe-Fx III has not fully booted, it will timeout when trying * to enable the audio streaming interface. A more generous timeout is * used here to detect when the Axe-Fx III has finished booting as the @@ -1008,6 +1016,8 @@ static int snd_usb_motu_microbookii_communicate(struct usb_device *dev, u8 *buf, { int err, actual_length; + if (snd_usb_pipe_sanity_check(dev, usb_sndintpipe(dev, 0x01))) + return -EINVAL; err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x01), buf, *length, &actual_length, 1000); if (err < 0) @@ -1018,6 +1028,8 @@ static int snd_usb_motu_microbookii_communicate(struct usb_device *dev, u8 *buf, memset(buf, 0, buf_size); + if (snd_usb_pipe_sanity_check(dev, usb_rcvintpipe(dev, 0x82))) + return -EINVAL; err = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x82), buf, buf_size, &actual_length, 1000); if (err < 0) From b545542a0b866f7975254e41c595836e9bc0ff2f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Jun 2019 10:07:19 +0900 Subject: [PATCH 497/626] ASoC: soc-core: call snd_soc_unbind_card() under mutex_lock; commit 34ac3c3eb8f0c07 ("ASoC: core: lock client_mutex while removing link components") added mutex_lock() at soc_remove_link_components(). Is is called from snd_soc_unbind_card() snd_soc_unbind_card() => soc_remove_link_components() soc_cleanup_card_resources() soc_remove_dai_links() => soc_remove_link_components() And, there are 2 way to call it. (1) snd_soc_unregister_component() ** mutex_lock() snd_soc_component_del_unlocked() => snd_soc_unbind_card() ** mutex_unlock() (2) snd_soc_unregister_card() => snd_soc_unbind_card() (1) case is already using mutex_lock() when it calles snd_soc_unbind_card(), thus, we will get lockdep warning. commit 495f926c68ddb90 ("ASoC: core: Fix deadlock in snd_soc_instantiate_card()") tried to fixup it, but still not enough. We still have lockdep warning when we try unbind/bind. We need mutex_lock() under snd_soc_unregister_card() instead of snd_remove_link_components()/snd_soc_unbind_card(). Fixes: 34ac3c3eb8f0c07 ("ASoC: core: lock client_mutex while removing link components") Fixes: 495f926c68ddb90 ("ASoC: core: Fix deadlock in snd_soc_instantiate_card()") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 41c0cfaf2db5..9138fcb15cd3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2837,14 +2837,12 @@ static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) snd_soc_dapm_shutdown(card); snd_soc_flush_all_delayed_work(card); - mutex_lock(&client_mutex); /* remove all components used by DAI links on this card */ for_each_comp_order(order) { for_each_card_rtds(card, rtd) { soc_remove_link_components(card, rtd, order); } } - mutex_unlock(&client_mutex); soc_cleanup_card_resources(card); if (!unregister) @@ -2863,7 +2861,9 @@ static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) */ int snd_soc_unregister_card(struct snd_soc_card *card) { + mutex_lock(&client_mutex); snd_soc_unbind_card(card, true); + mutex_unlock(&client_mutex); dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); return 0; From c2c928c93173f220955030e8440517b87ec7df92 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 21 Jun 2019 12:33:56 +0100 Subject: [PATCH 498/626] ASoC: core: Adapt for debugfs API change Back in ff9fb72bc07705c (debugfs: return error values, not NULL) the debugfs APIs were changed to return error pointers rather than NULL pointers on error, breaking the error checking in ASoC. Update the code to use IS_ERR() and log the codes that are returned as part of the error messages. Fixes: ff9fb72bc07705c (debugfs: return error values, not NULL) Signed-off-by: Mark Brown Cc: stable@vger.kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9138fcb15cd3..6aeba0d66ec5 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -158,9 +158,10 @@ static void soc_init_component_debugfs(struct snd_soc_component *component) component->card->debugfs_card_root); } - if (!component->debugfs_root) { + if (IS_ERR(component->debugfs_root)) { dev_warn(component->dev, - "ASoC: Failed to create component debugfs directory\n"); + "ASoC: Failed to create component debugfs directory: %ld\n", + PTR_ERR(component->debugfs_root)); return; } @@ -212,18 +213,21 @@ static void soc_init_card_debugfs(struct snd_soc_card *card) card->debugfs_card_root = debugfs_create_dir(card->name, snd_soc_debugfs_root); - if (!card->debugfs_card_root) { + if (IS_ERR(card->debugfs_card_root)) { dev_warn(card->dev, - "ASoC: Failed to create card debugfs directory\n"); + "ASoC: Failed to create card debugfs directory: %ld\n", + PTR_ERR(card->debugfs_card_root)); + card->debugfs_card_root = NULL; return; } card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, card->debugfs_card_root, &card->pop_time); - if (!card->debugfs_pop_time) + if (IS_ERR(card->debugfs_pop_time)) dev_warn(card->dev, - "ASoC: Failed to create pop time debugfs file\n"); + "ASoC: Failed to create pop time debugfs file: %ld\n", + PTR_ERR(card->debugfs_pop_time)); } static void soc_cleanup_card_debugfs(struct snd_soc_card *card) From ceaea851b9ea75f9ea2bbefb53ff0d4b27cd5a6e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 21 Jun 2019 12:33:57 +0100 Subject: [PATCH 499/626] ASoC: dapm: Adapt for debugfs API change Back in ff9fb72bc07705c (debugfs: return error values, not NULL) the debugfs APIs were changed to return error pointers rather than NULL pointers on error, breaking the error checking in ASoC. Update the code to use IS_ERR() and log the codes that are returned as part of the error messages. Fixes: ff9fb72bc07705c (debugfs: return error values, not NULL) Signed-off-by: Mark Brown Cc: stable@vger.kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5fc57af9cb6f..a248d88b8968 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2154,23 +2154,25 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, { struct dentry *d; - if (!parent) + if (!parent || IS_ERR(parent)) return; dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); - if (!dapm->debugfs_dapm) { + if (IS_ERR(dapm->debugfs_dapm)) { dev_warn(dapm->dev, - "ASoC: Failed to create DAPM debugfs directory\n"); + "ASoC: Failed to create DAPM debugfs directory %ld\n", + PTR_ERR(dapm->debugfs_dapm)); return; } d = debugfs_create_file("bias_level", 0444, dapm->debugfs_dapm, dapm, &dapm_bias_fops); - if (!d) + if (IS_ERR(d)) dev_warn(dapm->dev, - "ASoC: Failed to create bias level debugfs file\n"); + "ASoC: Failed to create bias level debugfs file: %ld\n", + PTR_ERR(d)); } static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) @@ -2184,10 +2186,10 @@ static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) d = debugfs_create_file(w->name, 0444, dapm->debugfs_dapm, w, &dapm_widget_power_fops); - if (!d) + if (IS_ERR(d)) dev_warn(w->dapm->dev, - "ASoC: Failed to create %s debugfs file\n", - w->name); + "ASoC: Failed to create %s debugfs file: %ld\n", + w->name, PTR_ERR(d)); } static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) From a2438253ba73ae51d9521c90ad8d3989bcdda74e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 20 Jun 2019 14:57:09 +0000 Subject: [PATCH 500/626] ASoC: SOF: Intel: hda: remove duplicated include from hda.c Remove duplicated include. Signed-off-by: YueHaibing Acked-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8754dfe75000..136f98bf5d7e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include "../ops.h" From 7d7db5d3c3d849c2f877be3b4c9afa7f5b5257c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 20 Jun 2019 09:49:17 +0900 Subject: [PATCH 501/626] ASoC: soc-core: move soc_find_component() move soc_find_component() next to snd_soc_is_matching_component(). This is prepare for soc_find_component() cleanup Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4cd77cd6c864..1b94119cfb0d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -760,6 +760,25 @@ static struct device_node return of_node; } +static int snd_soc_is_matching_component( + const struct snd_soc_dai_link_component *dlc, + struct snd_soc_component *component) +{ + struct device_node *component_of_node; + + if (!dlc) + return 0; + + component_of_node = soc_component_to_node(component); + + if (dlc->of_node && component_of_node != dlc->of_node) + return 0; + if (dlc->name && strcmp(component->name, dlc->name)) + return 0; + + return 1; +} + static struct snd_soc_component *soc_find_component( const struct device_node *of_node, const char *name) { @@ -782,25 +801,6 @@ static struct snd_soc_component *soc_find_component( return NULL; } -static int snd_soc_is_matching_component( - const struct snd_soc_dai_link_component *dlc, - struct snd_soc_component *component) -{ - struct device_node *component_of_node; - - if (!dlc) - return 0; - - component_of_node = soc_component_to_node(component); - - if (dlc->of_node && component_of_node != dlc->of_node) - return 0; - if (dlc->name && strcmp(component->name, dlc->name)) - return 0; - - return 1; -} - /** * snd_soc_find_dai - Find a registered DAI * From a9ec84966f6d887b9066029596eb361b5d2af214 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 20 Jun 2019 09:49:23 +0900 Subject: [PATCH 502/626] ASoC: soc-core: soc_find_component() uses snd_soc_is_matching_component() ALSA SoC already has snd_soc_is_matching_component() to confirming matching component, but, soc_find_component() has original implementation to confirm component. We shouldn't have duplicate implementation to do same things. This patch uses snd_soc_is_matching_component() at soc_find_component() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1b94119cfb0d..e6b95b7e2737 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -780,22 +780,18 @@ static int snd_soc_is_matching_component( } static struct snd_soc_component *soc_find_component( - const struct device_node *of_node, const char *name) + struct device_node *of_node, const char *name) { struct snd_soc_component *component; - struct device_node *component_of_node; + struct snd_soc_dai_link_component dlc; lockdep_assert_held(&client_mutex); for_each_component(component) { - if (of_node) { - component_of_node = soc_component_to_node(component); - - if (component_of_node == of_node) - return component; - } else if (name && strcmp(component->name, name) == 0) { + dlc.name = name; + dlc.of_node = of_node; + if (snd_soc_is_matching_component(&dlc, component)) return component; - } } return NULL; From c1e230f0f7a3cc640317aa78389258a2fa54bcde Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 20 Jun 2019 09:49:27 +0900 Subject: [PATCH 503/626] ASoC: soc-core: soc_find_component() uses snd_soc_dai_link_component soc_find_component() is using "of_node" and "name" to finding component, but we should use snd_soc_dai_link_component now, because it is created to such purpose. This patch uses snd_soc_dai_link_component for soc_find_component(). Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 45 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e6b95b7e2737..1749f4af91b6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -780,19 +780,15 @@ static int snd_soc_is_matching_component( } static struct snd_soc_component *soc_find_component( - struct device_node *of_node, const char *name) + const struct snd_soc_dai_link_component *dlc) { struct snd_soc_component *component; - struct snd_soc_dai_link_component dlc; lockdep_assert_held(&client_mutex); - for_each_component(component) { - dlc.name = name; - dlc.of_node = of_node; - if (snd_soc_is_matching_component(&dlc, component)) + for_each_component(component) + if (snd_soc_is_matching_component(dlc, component)) return component; - } return NULL; } @@ -1106,8 +1102,7 @@ static int soc_init_dai_link(struct snd_soc_card *card, * added to component list. */ if ((link->platforms->of_node || link->platforms->name) && - !soc_find_component(link->platforms->of_node, - link->platforms->name)) + !soc_find_component(link->platforms)) return -EPROBE_DEFER; } @@ -1136,7 +1131,7 @@ static int soc_init_dai_link(struct snd_soc_card *card, * component list. */ if ((link->cpus->of_node || link->cpus->name) && - !soc_find_component(link->cpus->of_node, link->cpus->name)) + !soc_find_component(link->cpus)) return -EPROBE_DEFER; /* @@ -1580,23 +1575,23 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) { struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; struct snd_soc_component *component; - const char *name; - struct device_node *codec_of_node; + struct snd_soc_dai_link_component dlc; if (aux_dev->codec_of_node || aux_dev->codec_name) { /* codecs, usually analog devices */ - name = aux_dev->codec_name; - codec_of_node = aux_dev->codec_of_node; - component = soc_find_component(codec_of_node, name); + dlc.name = aux_dev->codec_name; + dlc.of_node = aux_dev->codec_of_node; + component = soc_find_component(&dlc); if (!component) { - if (codec_of_node) - name = of_node_full_name(codec_of_node); + if (dlc.of_node) + dlc.name = of_node_full_name(dlc.of_node); goto err_defer; } } else if (aux_dev->name) { /* generic components */ - name = aux_dev->name; - component = soc_find_component(NULL, name); + dlc.name = aux_dev->name; + dlc.of_node = NULL; + component = soc_find_component(&dlc); if (!component) goto err_defer; } else { @@ -1610,7 +1605,7 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) return 0; err_defer: - dev_err(card->dev, "ASoC: %s not registered\n", name); + dev_err(card->dev, "ASoC: %s not registered\n", dlc.name); return -EPROBE_DEFER; } @@ -3661,11 +3656,11 @@ EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); int snd_soc_get_dai_id(struct device_node *ep) { struct snd_soc_component *component; - struct device_node *node; + struct snd_soc_dai_link_component dlc; int ret; - node = of_graph_get_port_parent(ep); - + dlc.of_node = of_graph_get_port_parent(ep); + dlc.name = NULL; /* * For example HDMI case, HDMI has video/sound port, * but ALSA SoC needs sound port number only. @@ -3674,13 +3669,13 @@ int snd_soc_get_dai_id(struct device_node *ep) */ ret = -ENOTSUPP; mutex_lock(&client_mutex); - component = soc_find_component(node, NULL); + component = soc_find_component(&dlc); if (component && component->driver->of_xlate_dai_id) ret = component->driver->of_xlate_dai_id(component, ep); mutex_unlock(&client_mutex); - of_node_put(node); + of_node_put(dlc.of_node); return ret; } From b9f2e25c599bbbf0646957e07ebb72b942c286cc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 20 Jun 2019 09:49:33 +0900 Subject: [PATCH 504/626] ASoC: soc-core: use soc_find_component() at snd_soc_find_dai() snd_soc_find_dai() finds component first via specified snd_soc_dai_link_component, and find DAI from it. We already have soc_find_component() to find component, but soc_find_dai() has original implementation to find component. We shouldn't have duplicate implementation to do same things. This patch uses soc_find_component() at soc_find_dai() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1749f4af91b6..358f1fbf9a30 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -813,9 +813,8 @@ struct snd_soc_dai *snd_soc_find_dai( lockdep_assert_held(&client_mutex); /* Find CPU DAI from registered DAIs */ - for_each_component(component) { - if (!snd_soc_is_matching_component(dlc, component)) - continue; + component = soc_find_component(dlc); + if (component) { for_each_component_dais(component, dai) { if (dlc->dai_name && strcmp(dai->name, dlc->dai_name) && (!dai->driver->name From 30b233b1cb4291d39ca08a95566721e8a52e5ee3 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Fri, 21 Jun 2019 17:58:08 +0200 Subject: [PATCH 505/626] ASoC: rk3399_gru_sound: Support 32, 44.1 and 88.2 kHz sample rates According to the datasheet the max98357a also supports 32, 44.1 and 88.2 kHz sample rate. This support was also introduced recently by commit fdf34366d324 ("ASoC: max98357a: add missing supported rates"). Actually the machine driver validates the supported sample rates but this is not really needed because the component driver can all apply whatever constraints are needed and do their own validation. So, remove the checks from the machine driver as are not needed at all. This way, we also support 32, 44.1 and 88.2 kHz sample rates and we get rid of the errors like the below. rk3399-gru-sound sound: rockchip_sound_max98357a_hw_params() doesn't support this sample rate: 44100 rk3399-gru-sound sound: ASoC: machine hw_params failed: -22 Signed-off-by: Enric Balletbo i Serra Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3399_gru_sound.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 879069fc0b94..769d5795919c 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -66,19 +66,7 @@ static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substrea unsigned int mclk; int ret; - /* max98357a supports these sample rates */ - switch (params_rate(params)) { - case 8000: - case 16000: - case 48000: - case 96000: - mclk = params_rate(params) * SOUND_FS; - break; - default: - dev_err(rtd->card->dev, "%s() doesn't support this sample rate: %d\n", - __func__, params_rate(params)); - return -EINVAL; - } + mclk = params_rate(params) * SOUND_FS; ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0); if (ret) { From 24043d60ff50ac3b72644ddbdfb7fa2df93fd648 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Mon, 24 Jun 2019 13:52:39 -0700 Subject: [PATCH 506/626] ASoC: rt5677: depop stereo dac Upon enabling the ASRC DAC we need a delay to avoid popping the speakers. Signed-off-by: Curtis Malainey Cc: Ross Zwisler Tested-by: Ross Zwisler Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 202af7135f07..7c9f263e1ffc 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -2611,7 +2611,8 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5677_ASRC_1, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("I2S3 ASRC", 1, RT5677_ASRC_1, 2, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("I2S4 ASRC", 1, RT5677_ASRC_1, 3, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5677_ASRC_2, 14, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5677_ASRC_2, 14, 0, + rt5677_filter_power_event, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY_S("DAC MONO2 L ASRC", 1, RT5677_ASRC_2, 13, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("DAC MONO2 R ASRC", 1, RT5677_ASRC_2, 12, 0, NULL, From d5fcaaba54ce729a018e50938aa6d355cffc7ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Har=C5=82ozi=C5=84ski?= Date: Thu, 13 Jun 2019 21:04:31 +0200 Subject: [PATCH 507/626] ASoC: Intel: Skylake: Use recommended SDxFMT programming sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For BXT platforms, the recommended sequence to program the SDxFMT is to first couple the stream, write the format and decouple again. For all other platforms said sequence remains unchanged. To prevent code duplication, IS_BXT (and consequently IS_CFL) macro is relocated to hda_codec.h file so it can be accessed by SKL driver. Signed-off-by: PaweÅ‚ HarÅ‚oziÅ„ski Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/hda_codec.h | 3 +++ sound/pci/hda/hda_intel.c | 3 --- sound/soc/intel/skylake/skl-pcm.c | 14 +++++++++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index cc7c8d42d4fd..ad46a082b00f 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -31,6 +31,9 @@ #include #include +#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) +#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) + /* * Structures */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 0741eae23f10..07144bcc7059 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -373,9 +373,6 @@ enum { ((pci)->device == 0x0d0c) || \ ((pci)->device == 0x160c)) -#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) -#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) - static char *driver_short_names[] = { [AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_PCH] = "HDA Intel PCH", diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index b00ee2730908..4fc78be2f751 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -141,6 +141,7 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) { struct hdac_bus *bus = dev_get_drvdata(dev); + struct skl *skl = bus_to_skl(bus); unsigned int format_val; struct hdac_stream *hstream; struct hdac_ext_stream *stream; @@ -165,7 +166,18 @@ int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) if (err < 0) return err; - err = snd_hdac_stream_setup(hdac_stream(stream)); + /* + * The recommended SDxFMT programming sequence for BXT + * platforms is to couple the stream before writing the format + */ + if (IS_BXT(skl->pci)) { + snd_hdac_ext_stream_decouple(bus, stream, false); + err = snd_hdac_stream_setup(hdac_stream(stream)); + snd_hdac_ext_stream_decouple(bus, stream, true); + } else { + err = snd_hdac_stream_setup(hdac_stream(stream)); + } + if (err < 0) return err; From 776cb3b80ede9ef4ad4c8aac22fcbdf4852b44cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:34 +0200 Subject: [PATCH 508/626] ASoC: Intel: Skylake: Initialize lists before access so they are safe to use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If skl_probe_work() was not run driver ends up dereferencing NULL pointer when operating on lists in skl_platform_unregister(). To fix this initialize lists in skl_create(). Also run cancel_work_sync() before all cleanup functions, so we don't end up unnecessarily running probe work. Easily reproducible with: while true; do modprobe snd_soc_skl; rmmod snd_soc_skl; done (with the assumption that relevant drivers are added to blacklist on system boot) Signed-off-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 3 --- sound/soc/intel/skylake/skl.c | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 4fc78be2f751..da01359cfdfd 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1498,9 +1498,6 @@ int skl_platform_register(struct device *dev) struct hdac_bus *bus = dev_get_drvdata(dev); struct skl *skl = bus_to_skl(bus); - INIT_LIST_HEAD(&skl->ppl_list); - INIT_LIST_HEAD(&skl->bind_list); - skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai), GFP_KERNEL); if (!skl->dais) { diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index f864f7b3df3a..6d6401410250 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -438,7 +438,6 @@ static int skl_free(struct hdac_bus *bus) snd_hdac_ext_bus_exit(bus); - cancel_work_sync(&skl->probe_work); if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); snd_hdac_i915_exit(bus); @@ -867,6 +866,9 @@ static int skl_create(struct pci_dev *pci, hbus = skl_to_hbus(skl); bus = skl_to_bus(skl); + INIT_LIST_HEAD(&skl->ppl_list); + INIT_LIST_HEAD(&skl->bind_list); + #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) ext_ops = snd_soc_hdac_hda_get_ops(); #endif @@ -1116,6 +1118,7 @@ static void skl_remove(struct pci_dev *pci) struct hdac_bus *bus = pci_get_drvdata(pci); struct skl *skl = bus_to_skl(bus); + cancel_work_sync(&skl->probe_work); release_firmware(skl->tplg); pm_runtime_get_noresume(&pci->dev); From 8a5b0177a7f6099ff534a4d9ce72673af5c3cade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:35 +0200 Subject: [PATCH 509/626] ALSA: hdac: Fix codec name after machine driver is unloaded and reloaded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently on each driver reload internal counter is being increased. It causes failure to enumerate driver devices, as they have hardcoded: .codec_name = "ehdaudio0D2", As there is currently no devices with multiple hda codecs and there is currently no established way to reliably differentiate, between them, always assign bus->idx = 0; This fixes a problem when we unload and reload machine driver idx gets incremented, so .codec_name would've needed to be set to "ehdaudio1D2" after first reload and so on. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Acked-by: Takashi Iwai Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/hda/ext/hdac_ext_bus.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index f33ba58b753c..71dad104ff8a 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -93,7 +93,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_ext_bus_ops *ext_ops) { int ret; - static int idx; /* check if io ops are provided, if not load the defaults */ if (io_ops == NULL) @@ -104,7 +103,12 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, return ret; bus->ext_ops = ext_ops; - bus->idx = idx++; + /* FIXME: + * Currently only one bus is supported, if there is device with more + * buses, bus->idx should be greater than 0, but there needs to be a + * reliable way to always assign same number. + */ + bus->idx = 0; bus->cmd_dma_state = true; return 0; From 09f448a415ece49ceb9d8f21f717aa3c0dbce851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:36 +0200 Subject: [PATCH 510/626] ASoC: compress: Fix memory leak from snd_soc_new_compress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change kzalloc to devm_kzalloc, so compr gets automatically freed when it's no longer needed. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 03d5b9ccd3fc..ddef4ff677ce 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -896,16 +896,14 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) else direction = SND_COMPRESS_CAPTURE; - compr = kzalloc(sizeof(*compr), GFP_KERNEL); + compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL); if (!compr) return -ENOMEM; compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), GFP_KERNEL); - if (!compr->ops) { - ret = -ENOMEM; - goto compr_err; - } + if (!compr->ops) + return -ENOMEM; if (rtd->dai_link->dynamic) { snprintf(new_name, sizeof(new_name), "(%s)", @@ -918,7 +916,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) dev_err(rtd->card->dev, "Compress ASoC: can't create compressed for %s: %d\n", rtd->dai_link->name, ret); - goto compr_err; + return ret; } rtd->pcm = be_pcm; @@ -954,7 +952,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) dev_err(component->dev, "Compress ASoC: can't create compress for codec %s: %d\n", component->name, ret); - goto compr_err; + return ret; } /* DAPM dai link stream work */ @@ -965,10 +963,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", codec_dai->name, cpu_dai->name); - return ret; -compr_err: - kfree(compr); - return ret; + return 0; } EXPORT_SYMBOL_GPL(snd_soc_new_compress); From 9f6115acc37ca4f1e064cd958b24bf457dfcef26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:37 +0200 Subject: [PATCH 511/626] ASoC: Intel: Skylake: Don't return failure on machine driver reload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we unload and reload machine driver, we shouldn't return that we failed to initialize. This allows to reload machine driver, without having to unload whole stack. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index da01359cfdfd..c03327ed94a0 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1439,11 +1439,6 @@ static int skl_platform_soc_probe(struct snd_soc_component *component) if (!ops) return -EIO; - if (!skl->skl_sst->is_first_boot) { - dev_err(component->dev, "DSP reports first boot done!!!\n"); - return -EIO; - } - /* * Disable dynamic clock and power gating during firmware * and library download From 5b8e4c1c66021dab1ed1683704f7ce47adbd7934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:39 +0200 Subject: [PATCH 512/626] ASoC: Intel: Skylake: Add function to cleanup debugfs interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently debugfs has no cleanup function. Add skl_debufs_exit function so we can clean after ourselves properly. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-debug.c | 9 +++++++++ sound/soc/intel/skylake/skl.h | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c index 5d7ac2ee7a3c..e81c3dafc0d0 100644 --- a/sound/soc/intel/skylake/skl-debug.c +++ b/sound/soc/intel/skylake/skl-debug.c @@ -259,3 +259,12 @@ err: debugfs_remove_recursive(d->fs); return NULL; } + +void skl_debugfs_exit(struct skl *skl) +{ + struct skl_debug *d = skl->debugfs; + + debugfs_remove_recursive(d->fs); + + d = NULL; +} diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 85f8bb6687dc..d2e269867a44 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -164,6 +164,7 @@ struct skl_module_cfg; #ifdef CONFIG_DEBUG_FS struct skl_debug *skl_debugfs_init(struct skl *skl); +void skl_debugfs_exit(struct skl *skl); void skl_debug_init_module(struct skl_debug *d, struct snd_soc_dapm_widget *w, struct skl_module_cfg *mconfig); @@ -172,6 +173,10 @@ static inline struct skl_debug *skl_debugfs_init(struct skl *skl) { return NULL; } + +static inline void skl_debugfs_exit(struct skl *skl) +{} + static inline void skl_debug_init_module(struct skl_debug *d, struct snd_soc_dapm_widget *w, struct skl_module_cfg *mconfig) From e79986ce50d65f490c6eab3aaea1ff2ab5df5d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:40 +0200 Subject: [PATCH 513/626] ASoC: Intel: Skylake: Properly cleanup on component removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we remove component we need to reverse things which were done on init, this consists of topology cleanup, lists cleanup and releasing firmware. Currently cleanup handlers are put in wrong places or otherwise missing. So add proper component cleanup function and perform cleanups in it. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 8 ++++++-- sound/soc/intel/skylake/skl-topology.c | 15 +++++++++++++++ sound/soc/intel/skylake/skl-topology.h | 2 ++ sound/soc/intel/skylake/skl.c | 2 -- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index c03327ed94a0..75100b44b49a 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1471,8 +1471,12 @@ static int skl_platform_soc_probe(struct snd_soc_component *component) static void skl_pcm_remove(struct snd_soc_component *component) { - /* remove topology */ - snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); + struct hdac_bus *bus = dev_get_drvdata(component->dev); + struct skl *skl = bus_to_skl(bus); + + skl_tplg_exit(component, bus); + + skl_debugfs_exit(skl); } static const struct snd_soc_component_driver skl_component = { diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 9fd756bcc740..99825dda34af 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -3757,3 +3757,18 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) return 0; } + +void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) +{ + struct skl *skl = bus_to_skl(bus); + struct skl_pipeline *ppl, *tmp; + + if (!list_empty(&skl->ppl_list)) + list_for_each_entry_safe(ppl, tmp, &skl->ppl_list, node) + list_del(&ppl->node); + + /* clean up topology */ + snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); + + release_firmware(skl->tplg); +} diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 9311e248b6f9..370191a79bc1 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -471,6 +471,8 @@ void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai, struct skl_pipe_params *params, int stream); int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *ebus); +void skl_tplg_exit(struct snd_soc_component *component, + struct hdac_bus *bus); struct skl_module_cfg *skl_tplg_fe_get_cpr_module( struct snd_soc_dai *dai, int stream); int skl_tplg_update_pipe_params(struct device *dev, diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 6d6401410250..e4881ff427ea 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -1119,14 +1119,12 @@ static void skl_remove(struct pci_dev *pci) struct skl *skl = bus_to_skl(bus); cancel_work_sync(&skl->probe_work); - release_firmware(skl->tplg); pm_runtime_get_noresume(&pci->dev); /* codec removal, invoke bus_device_remove */ snd_hdac_ext_bus_device_remove(bus); - skl->debugfs = NULL; skl_platform_unregister(&pci->dev); skl_free_dsp(skl); skl_machine_device_unregister(skl); From 6ee927f2f014668c5fe920d0fd1a6ad48671bfce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:41 +0200 Subject: [PATCH 514/626] ASoC: Intel: Skylake: Fix NULL ptr dereference when unloading clk dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When driver is probed, we iterate over NHLT and check if clk entries are present. For each such entry we call register_skl_clk and keep the result in data->clk[]. Currently data->clk is sparsely indexed using NHLT table iterator, while when freeing we use number of registered entries. Let's just use data->avail_clk_cnt as index, so it can be reset back in unregister_src_clk. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-ssp-clk.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index cda1b5fa7436..5bb6e40d4d3e 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c @@ -276,10 +276,8 @@ static void unregister_parent_src_clk(struct skl_clk_parent *pclk, static void unregister_src_clk(struct skl_clk_data *dclk) { - u8 cnt = dclk->avail_clk_cnt; - - while (cnt--) - clkdev_drop(dclk->clk[cnt]->lookup); + while (dclk->avail_clk_cnt--) + clkdev_drop(dclk->clk[dclk->avail_clk_cnt]->lookup); } static int skl_register_parent_clks(struct device *dev, @@ -381,13 +379,13 @@ static int skl_clk_dev_probe(struct platform_device *pdev) if (clks[i].rate_cfg[0].rate == 0) continue; - data->clk[i] = register_skl_clk(dev, &clks[i], clk_pdata, i); - if (IS_ERR(data->clk[i])) { - ret = PTR_ERR(data->clk[i]); + data->clk[data->avail_clk_cnt] = register_skl_clk(dev, + &clks[i], clk_pdata, i); + + if (IS_ERR(data->clk[data->avail_clk_cnt])) { + ret = PTR_ERR(data->clk[data->avail_clk_cnt++]); goto err_unreg_skl_clk; } - - data->avail_clk_cnt++; } platform_set_drvdata(pdev, data); From 0f6ff78540bd1b4df1e0f17806b0ce2e1dff0d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:42 +0200 Subject: [PATCH 515/626] ASoC: Intel: hdac_hdmi: Set ops to NULL on remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we unload Skylake driver we may end up calling hdac_component_master_unbind(), it uses acomp->audio_ops, which we set in hdmi_codec_probe(), so we need to set it to NULL in hdmi_codec_remove(), otherwise we will dereference no longer existing pointer. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 660e0587f399..da3835b703f5 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1867,6 +1867,12 @@ static void hdmi_codec_remove(struct snd_soc_component *component) { struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); struct hdac_device *hdev = hdmi->hdev; + int ret; + + ret = snd_hdac_acomp_register_notifier(hdev->bus, NULL); + if (ret < 0) + dev_err(&hdev->dev, "notifier unregister failed: err: %d\n", + ret); pm_runtime_disable(&hdev->dev); } From 3cde818cd02b9602270092f6c06c727c70f84d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:43 +0200 Subject: [PATCH 516/626] ASoC: topology: Consolidate how dtexts and dvalues are freed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provide helper functions and use them to free dtexts and dvalues in topology. This is followup cleanup after related changes in this area as suggested in: https://mailman.alsa-project.org/pipermail/alsa-devel/2019-January/144761.html Signed-off-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 41 +++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index b538412e4bcf..a926c2afbe05 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -86,6 +86,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget * snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_widget *widget); +static void soc_tplg_denum_remove_texts(struct soc_enum *se); +static void soc_tplg_denum_remove_values(struct soc_enum *se); /* check we dont overflow the data for this control chunk */ static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size, @@ -398,7 +400,6 @@ static void remove_enum(struct snd_soc_component *comp, { struct snd_card *card = comp->card->snd_card; struct soc_enum *se = container_of(dobj, struct soc_enum, dobj); - int i; if (pass != SOC_TPLG_PASS_MIXER) return; @@ -409,10 +410,8 @@ static void remove_enum(struct snd_soc_component *comp, snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); - kfree(dobj->control.dvalues); - for (i = 0; i < se->items; i++) - kfree(dobj->control.dtexts[i]); - kfree(dobj->control.dtexts); + soc_tplg_denum_remove_values(se); + soc_tplg_denum_remove_texts(se); kfree(se); } @@ -480,15 +479,12 @@ static void remove_widget(struct snd_soc_component *comp, struct snd_kcontrol *kcontrol = w->kcontrols[i]; struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; - int j; snd_ctl_remove(card, kcontrol); /* free enum kcontrol's dvalues and dtexts */ - kfree(se->dobj.control.dvalues); - for (j = 0; j < se->items; j++) - kfree(se->dobj.control.dtexts[j]); - kfree(se->dobj.control.dtexts); + soc_tplg_denum_remove_values(se); + soc_tplg_denum_remove_texts(se); kfree(se); kfree(w->kcontrol_news[i].name); @@ -956,14 +952,23 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se, } } + se->items = le32_to_cpu(ec->items); se->texts = (const char * const *)se->dobj.control.dtexts; return 0; err: + se->items = i; + soc_tplg_denum_remove_texts(se); + return ret; +} + +static inline void soc_tplg_denum_remove_texts(struct soc_enum *se) +{ + int i = se->items; + for (--i; i >= 0; i--) kfree(se->dobj.control.dtexts[i]); kfree(se->dobj.control.dtexts); - return ret; } static int soc_tplg_denum_create_values(struct soc_enum *se, @@ -988,6 +993,11 @@ static int soc_tplg_denum_create_values(struct soc_enum *se, return 0; } +static inline void soc_tplg_denum_remove_values(struct soc_enum *se) +{ + kfree(se->dobj.control.dvalues); +} + static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, size_t size) { @@ -1035,7 +1045,6 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, se->shift_r = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); - se->items = le32_to_cpu(ec->items); se->mask = le32_to_cpu(ec->mask); se->dobj.index = tplg->index; se->dobj.type = SND_SOC_DOBJ_ENUM; @@ -1381,7 +1390,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( struct snd_kcontrol_new *kc; struct snd_soc_tplg_enum_control *ec; struct soc_enum *se; - int i, j, err; + int i, err; kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL); if (kc == NULL) @@ -1476,10 +1485,8 @@ err_se: if (!se) continue; - kfree(se->dobj.control.dvalues); - for (j = 0; j < ec->items; j++) - kfree(se->dobj.control.dtexts[j]); - kfree(se->dobj.control.dtexts); + soc_tplg_denum_remove_values(se); + soc_tplg_denum_remove_texts(se); kfree(se); kfree(kc[i].name); From 9f90af3a995298d2a49b23b896f075d6a1cc8a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Jun 2019 13:36:44 +0200 Subject: [PATCH 517/626] ASoC: topology: Consolidate and fix asoc_tplg_dapm_widget_*_create flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a few soc_tplg_dapm_widget_*_create functions with similar content, but slightly different flow, unify their flow and make sure that we go to error handler and free memory in case of failure. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Acked-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 77 ++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index a926c2afbe05..fc1f1d6f9e92 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1310,14 +1310,15 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( for (i = 0; i < num_kcontrols; i++) { mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; - sm = kzalloc(sizeof(*sm), GFP_KERNEL); - if (sm == NULL) - goto err; /* validate kcontrol */ if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - goto err_str; + goto err_sm; + + sm = kzalloc(sizeof(*sm), GFP_KERNEL); + if (sm == NULL) + goto err_sm; tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + le32_to_cpu(mc->priv.size)); @@ -1327,7 +1328,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( kc[i].name = kstrdup(mc->hdr.name, GFP_KERNEL); if (kc[i].name == NULL) - goto err_str; + goto err_sm; kc[i].private_value = (long)sm; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc[i].access = mc->hdr.access; @@ -1353,8 +1354,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], tplg); if (err) { soc_control_err(tplg, &mc->hdr, mc->hdr.name); - kfree(sm); - continue; + goto err_sm; } /* create any TLV data */ @@ -1367,20 +1367,19 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( dev_err(tplg->dev, "ASoC: failed to init %s\n", mc->hdr.name); soc_tplg_free_tlv(tplg, &kc[i]); - kfree(sm); - continue; + goto err_sm; } } return kc; -err_str: - kfree(sm); -err: - for (--i; i >= 0; i--) { - kfree((void *)kc[i].private_value); +err_sm: + for (; i >= 0; i--) { + sm = (struct soc_mixer_control *)kc[i].private_value; + kfree(sm); kfree(kc[i].name); } kfree(kc); + return NULL; } @@ -1401,11 +1400,11 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( /* validate kcontrol */ if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - goto err; + goto err_se; se = kzalloc(sizeof(*se), GFP_KERNEL); if (se == NULL) - goto err; + goto err_se; tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + ec->priv.size); @@ -1414,10 +1413,8 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( ec->hdr.name); kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL); - if (kc[i].name == NULL) { - kfree(se); + if (kc[i].name == NULL) goto err_se; - } kc[i].private_value = (long)se; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc[i].access = ec->hdr.access; @@ -1482,44 +1479,43 @@ err_se: for (; i >= 0; i--) { /* free values and texts */ se = (struct soc_enum *)kc[i].private_value; - if (!se) - continue; - soc_tplg_denum_remove_values(se); - soc_tplg_denum_remove_texts(se); + if (se) { + soc_tplg_denum_remove_values(se); + soc_tplg_denum_remove_texts(se); + } kfree(se); kfree(kc[i].name); } -err: kfree(kc); return NULL; } static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( - struct soc_tplg *tplg, int count) + struct soc_tplg *tplg, int num_kcontrols) { struct snd_soc_tplg_bytes_control *be; - struct soc_bytes_ext *sbe; + struct soc_bytes_ext *sbe; struct snd_kcontrol_new *kc; int i, err; - kc = kcalloc(count, sizeof(*kc), GFP_KERNEL); + kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL); if (!kc) return NULL; - for (i = 0; i < count; i++) { + for (i = 0; i < num_kcontrols; i++) { be = (struct snd_soc_tplg_bytes_control *)tplg->pos; /* validate kcontrol */ if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - goto err; + goto err_sbe; sbe = kzalloc(sizeof(*sbe), GFP_KERNEL); if (sbe == NULL) - goto err; + goto err_sbe; tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + le32_to_cpu(be->priv.size)); @@ -1529,10 +1525,8 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( be->hdr.name, be->hdr.access); kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL); - if (kc[i].name == NULL) { - kfree(sbe); - goto err; - } + if (kc[i].name == NULL) + goto err_sbe; kc[i].private_value = (long)sbe; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc[i].access = be->hdr.access; @@ -1544,8 +1538,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], tplg); if (err) { soc_control_err(tplg, &be->hdr, be->hdr.name); - kfree(sbe); - continue; + goto err_sbe; } /* pass control to driver for optional further init */ @@ -1554,20 +1547,20 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name); - kfree(sbe); - continue; + goto err_sbe; } } return kc; -err: - for (--i; i >= 0; i--) { - kfree((void *)kc[i].private_value); +err_sbe: + for (; i >= 0; i--) { + sbe = (struct soc_bytes_ext *)kc[i].private_value; + kfree(sbe); kfree(kc[i].name); } - kfree(kc); + return NULL; } From 078759399ff74e2e6f5e208c61924d1b7d66e5d8 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 13 Jun 2019 21:04:32 +0200 Subject: [PATCH 518/626] ASoC: Intel: Skylake: Read HIPCT extension before clearing DONE bit Host clears DONE bit to signal IPC target it has completed the operation. Once this is done, IPC target i.e. DSP may proceed with the next reply, filling registers with new portion of data. Because of this, host should always read all registers prior to clearing DONE and BUSY bits to ensure no desynchronization happens the time in between clearing bits and reading message data (here, extension). Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/cnl-sst.c | 2 +- sound/soc/intel/skylake/skl-sst-ipc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index 245df1067ba8..759ea59615ca 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -313,6 +313,7 @@ static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) hipcida = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDA); hipctdr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDR); + hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); /* reply message from dsp */ if (hipcida & CNL_ADSP_REG_HIPCIDA_DONE) { @@ -332,7 +333,6 @@ static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) /* new message from dsp */ if (hipctdr & CNL_ADSP_REG_HIPCTDR_BUSY) { - hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); header.primary = hipctdr; header.extension = hipctdd; dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 9f3ce73593ae..5c9206dc7932 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -511,6 +511,7 @@ irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE); hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT); + hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE); /* reply message from DSP */ if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) { @@ -530,7 +531,6 @@ irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) /* New message from DSP */ if (hipct & SKL_ADSP_REG_HIPCT_BUSY) { - hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE); header.primary = hipct; header.extension = hipcte; dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n", From 26ae20490809db30677dfd54f81a73ce77ba2df1 Mon Sep 17 00:00:00 2001 From: Gustaw Lewandowski Date: Thu, 13 Jun 2019 21:04:33 +0200 Subject: [PATCH 519/626] ASoC: Intel: Fix race condition in IPC rx list Since there are multiple IPCs being sent in a short span of time, there is a possibility of more than one message being on the Rx list after receiving response from firmware. In such cases, when the first notification of interrupt from firmware is received, driver retrieves the message from the Rx list but does not delete it from the list till the next lock. In the meantime, when another interrupt is received from the firmware, driver is reading the previous message again since the previous message has not been removed from the list. Signed-off-by: Gustaw Lewandowski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-sst-ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 5c9206dc7932..5094205a243f 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -344,6 +344,7 @@ static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc, msg = list_first_entry(&ipc->rx_list, struct ipc_message, list); + list_del(&msg->list); out: return msg; @@ -488,7 +489,6 @@ void skl_ipc_process_reply(struct sst_generic_ipc *ipc, } spin_lock_irqsave(&ipc->dsp->spinlock, flags); - list_del(&msg->list); sst_ipc_tx_msg_reply_complete(ipc, msg); spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); } From 9f4f42d710d417745cff05845f93370126f77ff7 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 13 Jun 2019 21:04:34 +0200 Subject: [PATCH 520/626] ASoC: Intel: Common: Fix NULL dereference in tx_wait_done rx_data and rx_bytes present for tx_wait_done are optional parameters. If not provided, function should not attempt to copy received data. This change fixes memcpy NULL pointer dereference issue occurring when optional rx_data is NULL while received message size is non-zero. Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/common/sst-ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index dcff13802c00..fc3340f1da3a 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -71,7 +71,7 @@ static int tx_wait_done(struct sst_generic_ipc *ipc, } else { /* copy the data returned from DSP */ - if (msg->rx_size) + if (rx_data) memcpy(rx_data, msg->rx_data, msg->rx_size); ret = msg->errno; } From 02923faa6b29ac0423f1d5ff8c13c5eeb4e5669b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 13 Jun 2019 21:04:35 +0200 Subject: [PATCH 521/626] ASoC: Intel: Skylake: Reset pipeline before its deletion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before actual deletion, pipeline should enter RESET state. Currently, pipe skips this checkpoint and goes straight to the finish line. This is not the expected path by the FW, so correct it. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index df01dc952521..79baf90e6116 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -1265,10 +1265,10 @@ int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) } /* - * A pipeline needs to be deleted on cleanup. If a pipeline is running, then - * pause the pipeline first and then delete it - * The pipe delete is done by sending delete pipeline IPC. DSP will stop the - * DMA engines and releases resources + * A pipeline needs to be deleted on cleanup. If a pipeline is running, + * then pause it first. Before actual deletion, pipeline should enter + * reset state. Finish the procedure by sending delete pipeline IPC. + * DSP will stop the DMA engines and release resources */ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) { @@ -1276,6 +1276,10 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); + /* If pipe was not created in FW, do not try to delete it */ + if (pipe->state < SKL_PIPE_CREATED) + return 0; + /* If pipe is started, do stop the pipe in FW. */ if (pipe->state >= SKL_PIPE_STARTED) { ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); @@ -1287,9 +1291,14 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) pipe->state = SKL_PIPE_PAUSED; } - /* If pipe was not created in FW, do not try to delete it */ - if (pipe->state < SKL_PIPE_CREATED) - return 0; + /* reset pipe state before deletion */ + ret = skl_set_pipe_state(ctx, pipe, PPL_RESET); + if (ret < 0) { + dev_err(ctx->dev, "Failed to reset pipe ret=%d\n", ret); + return ret; + } + + pipe->state = SKL_PIPE_RESET; ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); if (ret < 0) { From a8cd7066f0422f378902770034ddac1720d0e032 Mon Sep 17 00:00:00 2001 From: Kamil Lulko Date: Thu, 13 Jun 2019 21:04:36 +0200 Subject: [PATCH 522/626] ASoC: Intel: Skylake: Strip T and L from TLV IPCs cAVS modules do not require Type and Length header within the set_module_params IPC. This is also true for Vendor modules. The userspace (like tinymix) always appends this header to TLV controls which are used for set_module_params. Simply assume this header is always present in the payload and omit it from the IPC. Signed-off-by: Kamil Lulko Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 99825dda34af..c353eb14ce36 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1492,22 +1492,18 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, struct skl *skl = get_skl_ctx(w->dapm->dev); if (ac->params) { + /* + * Widget data is expected to be stripped of T and L + */ + size -= 2 * sizeof(unsigned int); + data += 2; + if (size > ac->max) return -EINVAL; - ac->size = size; - /* - * if the param_is is of type Vendor, firmware expects actual - * parameter id and size from the control. - */ - if (ac->param_id == SKL_PARAM_VENDOR_ID) { - if (copy_from_user(ac->params, data, size)) - return -EFAULT; - } else { - if (copy_from_user(ac->params, - data + 2, size)) - return -EFAULT; - } + + if (copy_from_user(ac->params, data, size)) + return -EFAULT; if (w->power) return skl_set_module_params(skl->skl_sst, From da7260cc8d1dc3564eb4f33550b0525541d71a47 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Wed, 26 Jun 2019 13:49:46 +0300 Subject: [PATCH 523/626] ASoC: codecs: ad193x: Fix memory corruption on BE 64b systems Since change_bit() requires unsigned long*, making this cast on an unsigned int variable will change a wrong bit on BE platforms, causing memory corruption. Replace this function with a simple XOR. Fixes: 90f6e6803139 ("ASoC: codecs: ad193x: Fix frame polarity for DSP_A format") Reported-by: Dan Carpenter Signed-off-by: Codrin Ciubotariu Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 96d7cb2e4a56..16e2d334bbe0 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -241,10 +241,8 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, } /* For DSP_*, LRCLK's polarity must be inverted */ - if (fmt & SND_SOC_DAIFMT_DSP_A) { - change_bit(ffs(AD193X_DAC_LEFT_HIGH) - 1, - (unsigned long *)&dac_fmt); - } + if (fmt & SND_SOC_DAIFMT_DSP_A) + dac_fmt ^= AD193X_DAC_LEFT_HIGH; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ From 472e5df0137e10fbaed0eef38c9bdf99e088ff13 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 25 Jun 2019 16:37:27 +0100 Subject: [PATCH 524/626] ASoC: madera: Update SPDX headers The madera driver was merged too late to catch Thomas Gleixner's cleanup of the SPDX headers tree wide. Update the headers to match what was done in that patch. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- include/dt-bindings/sound/madera.h | 6 +----- include/sound/madera-pdata.h | 6 +----- sound/soc/codecs/cs47l35.c | 6 +----- sound/soc/codecs/cs47l85.c | 6 +----- sound/soc/codecs/cs47l90.c | 6 +----- sound/soc/codecs/madera.c | 6 +----- sound/soc/codecs/madera.h | 6 +----- 7 files changed, 7 insertions(+), 35 deletions(-) diff --git a/include/dt-bindings/sound/madera.h b/include/dt-bindings/sound/madera.h index 9ff4eae5259b..d0096d5eb0da 100644 --- a/include/dt-bindings/sound/madera.h +++ b/include/dt-bindings/sound/madera.h @@ -1,13 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Device Tree defines for Madera codecs * * Copyright (C) 2016-2017 Cirrus Logic, Inc. and * Cirrus Logic International Semiconductor Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef DT_BINDINGS_SOUND_MADERA_H diff --git a/include/sound/madera-pdata.h b/include/sound/madera-pdata.h index 441decefb7f3..e3060f48f108 100644 --- a/include/sound/madera-pdata.h +++ b/include/sound/madera-pdata.h @@ -1,13 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Platform data for Madera codec driver * * Copyright (C) 2016-2019 Cirrus Logic, Inc. and * Cirrus Logic International Semiconductor Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef MADERA_CODEC_PDATA_H diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index 02f193dadd41..511d0d6fa962 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // ALSA SoC Audio driver for CS47L35 codec // // Copyright (C) 2015-2019 Cirrus Logic, Inc. and // Cirrus Logic International Semiconductor Ltd. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by the -// Free Software Foundation; version 2. -// #include #include diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 4c4bae6e2c57..32fe7ffb7526 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // ALSA SoC Audio driver for CS47L85 codec // // Copyright (C) 2015-2019 Cirrus Logic, Inc. and // Cirrus Logic International Semiconductor Ltd. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by the -// Free Software Foundation; version 2. -// #include #include diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 83c4e4628bde..c4ecb0e6911a 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // ALSA SoC Audio driver for CS47L90 codec // // Copyright (C) 2015-2019 Cirrus Logic, Inc. and // Cirrus Logic International Semiconductor Ltd. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by the -// Free Software Foundation; version 2. -// #include #include diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 6146c7a070cb..1b1be19a2f99 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // Cirrus Logic Madera class codecs common support // // Copyright (C) 2015-2019 Cirrus Logic, Inc. and // Cirrus Logic International Semiconductor Ltd. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by the -// Free Software Foundation; version 2. -// #include #include diff --git a/sound/soc/codecs/madera.h b/sound/soc/codecs/madera.h index aa2db156582b..0af66f280770 100644 --- a/sound/soc/codecs/madera.h +++ b/sound/soc/codecs/madera.h @@ -1,13 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Cirrus Logic Madera class codecs common support * * Copyright (C) 2015-2018 Cirrus Logic, Inc. and * Cirrus Logic International Semiconductor Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; version 2. */ #ifndef ASOC_MADERA_H From dfea7b2c5c7eaf657086bb95d61814d7e04d1409 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Jun 2019 10:58:56 +0900 Subject: [PATCH 525/626] ASoC: rsnd: ssiu: tidyup SSI_MODE1/2 settings R-Car Sound can use pin sharing and multi-SSI for SSI0/1/2/3/4/9. Because complex HW settings and spaghetti code, the settings for SSI9 pin sharing with SSI0 doesn't work. This patch tidyup settings for it. Reported-by: Hien Dang Signed-off-by: Kuninori Morimoto Tested-by: Chaoliang Qin Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssiu.c | 92 +++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 2347f3404c06..f35d88211887 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -60,11 +60,11 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_dai *rdai = rsnd_io_to_rdai(io); - u32 multi_ssi_slaves = rsnd_ssi_multi_slaves_runtime(io); + u32 ssis = rsnd_ssi_multi_slaves_runtime(io); int use_busif = rsnd_ssi_use_busif(io); int id = rsnd_mod_id(mod); - u32 mask1, val1; - u32 mask2, val2; + int is_clk_master = rsnd_rdai_is_clk_master(rdai); + u32 val1, val2; int i; /* clear status */ @@ -89,57 +89,53 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod, rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id); /* - * SSI_MODE1 + * SSI_MODE1 / SSI_MODE2 + * + * FIXME + * sharing/multi with SSI0 are mainly supported */ - mask1 = (1 << 4) | (1 << 20); /* mask sync bit */ - mask2 = (1 << 4); /* mask sync bit */ - val1 = val2 = 0; - if (id == 8) { + val1 = rsnd_mod_read(mod, SSI_MODE1); + val2 = rsnd_mod_read(mod, SSI_MODE2); + if (rsnd_ssi_is_pin_sharing(io)) { + + ssis |= (1 << id); + + } else if (ssis) { /* - * SSI8 pin is sharing with SSI7, nothing to do. + * Multi SSI + * + * set synchronized bit here */ - } else if (rsnd_ssi_is_pin_sharing(io)) { - int shift = -1; - switch (id) { - case 1: - shift = 0; - break; - case 2: - shift = 2; - break; - case 4: - shift = 16; - break; - default: - return -EINVAL; - } - - mask1 |= 0x3 << shift; - val1 = rsnd_rdai_is_clk_master(rdai) ? - 0x2 << shift : 0x1 << shift; - - } else if (multi_ssi_slaves) { - - mask2 |= 0x00000007; - mask1 |= 0x0000000f; - - switch (multi_ssi_slaves) { - case 0x0206: /* SSI0/1/2/9 */ - val2 = (1 << 4) | /* SSI0129 sync */ - (rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1); - /* fall through */ - case 0x0006: /* SSI0/1/2 */ - val1 = rsnd_rdai_is_clk_master(rdai) ? - 0xa : 0x5; - - if (!val2) /* SSI012 sync */ - val1 |= (1 << 4); - } + /* SSI4 is synchronized with SSI3 */ + if (ssis & (1 << 4)) + val1 |= (1 << 20); + /* SSI012 are synchronized */ + if (ssis == 0x0006) + val1 |= (1 << 4); + /* SSI0129 are synchronized */ + if (ssis == 0x0206) + val2 |= (1 << 4); } - rsnd_mod_bset(mod, SSI_MODE1, mask1, val1); - rsnd_mod_bset(mod, SSI_MODE2, mask2, val2); + /* SSI1 is sharing pin with SSI0 */ + if (ssis & (1 << 1)) + val1 |= is_clk_master ? 0x2 : 0x1; + + /* SSI2 is sharing pin with SSI0 */ + if (ssis & (1 << 2)) + val1 |= is_clk_master ? 0x2 << 2 : + 0x1 << 2; + /* SSI4 is sharing pin with SSI3 */ + if (ssis & (1 << 4)) + val1 |= is_clk_master ? 0x2 << 16 : + 0x1 << 16; + /* SSI9 is sharing pin with SSI0 */ + if (ssis & (1 << 9)) + val2 |= is_clk_master ? 0x2 : 0x1; + + rsnd_mod_bset(mod, SSI_MODE1, 0x0013001f, val1); + rsnd_mod_bset(mod, SSI_MODE2, 0x00000017, val2); return 0; } From 526a6d45b013d45fdddd420860c69fb29fed3d62 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Jun 2019 11:00:05 +0900 Subject: [PATCH 526/626] ASoC: rsnd: add missing pin sharing with SSI9 When SSI9 is sharing pin with SSI0, we need to care about it, but is missing. This patch fixup it. Reported-by: Hien Dang Signed-off-by: Kuninori Morimoto Tested-by: Chaoliang Qin Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 1 + sound/soc/sh/rcar/ssi.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index e821ccc70f47..fce4e050a9b7 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -87,6 +87,7 @@ static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) switch (id) { case 1: case 2: + case 9: ws = 0; break; case 4: diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 44bda210256e..f6a7466622ea 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -740,6 +740,7 @@ static void rsnd_ssi_parent_attach(struct rsnd_mod *mod, switch (rsnd_mod_id(mod)) { case 1: case 2: + case 9: rsnd_dai_connect(rsnd_ssi_mod_get(priv, 0), io, RSND_MOD_SSIP); break; case 4: From e3303268f9cfa4eb7c2217df471417d4327109fd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Jun 2019 10:40:59 +0900 Subject: [PATCH 527/626] ASoC: soc-core: don't use soc_find_component() at snd_soc_find_dai() commit b9f2e25c599bb ("ASoC: soc-core: use soc_find_component() at snd_soc_find_dai()") used soc_find_component() at snd_soc_find_dai(), but, some CPU driver has CPU component for DAI and Platform component, for example generic DMAEngine component. In such case, CPU component and Platform component have same of_node / name. Here soc_find_component() returns *1st* found component. Thus, we shouldn't use soc_find_component() at snd_soc_find_dai(). This patch fixup this it, and add comment to indicate this limitation. Fixes: commit b9f2e25c599bb ("ASoC: soc-core: use soc_find_component() at snd_soc_find_dai()") Reported-by: Dmitry Osipenko Reported-by: Jon Hunter Signed-off-by: Kuninori Morimoto Tested-by: Jon Hunter Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 358f1fbf9a30..8ccaf63e428c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -786,6 +786,14 @@ static struct snd_soc_component *soc_find_component( lockdep_assert_held(&client_mutex); + /* + * NOTE + * + * It returns *1st* found component, but some driver + * has few components by same of_node/name + * ex) + * CPU component and generic DMAEngine component + */ for_each_component(component) if (snd_soc_is_matching_component(dlc, component)) return component; @@ -813,8 +821,9 @@ struct snd_soc_dai *snd_soc_find_dai( lockdep_assert_held(&client_mutex); /* Find CPU DAI from registered DAIs */ - component = soc_find_component(dlc); - if (component) { + for_each_component(component) { + if (!snd_soc_is_matching_component(dlc, component)) + continue; for_each_component_dais(component, dai) { if (dlc->dai_name && strcmp(dai->name, dlc->dai_name) && (!dai->driver->name From 3fc4147653130c5d49d07e06186628e29ba9f39d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 27 Jun 2019 17:58:53 +0100 Subject: [PATCH 528/626] ALSA: xen-front: fix unintention integer overflow on left shifts Shifting the integer value 1 is evaluated using 32-bit arithmetic and then used in an expression that expects a 64-bit value, so there is potentially an integer overflow. Fix this by using the BIT_ULL macro to perform the shift. [ Note: as of the time being, no actual integer overflow hits because all values are less than 32bit, not including the extended 3-byte or DSD formats. But this is the right fix for future usage, of course. -- tiwai ] Addresses-Coverity: ("Unintentional integer overflow") Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/xen/xen_snd_front_alsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/xen/xen_snd_front_alsa.c b/sound/xen/xen_snd_front_alsa.c index b14ab512c2ce..e01631959ed8 100644 --- a/sound/xen/xen_snd_front_alsa.c +++ b/sound/xen/xen_snd_front_alsa.c @@ -196,7 +196,7 @@ static u64 to_sndif_formats_mask(u64 alsa_formats) mask = 0; for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++) if (pcm_format_to_bits(ALSA_SNDIF_FORMATS[i].alsa) & alsa_formats) - mask |= 1 << ALSA_SNDIF_FORMATS[i].sndif; + mask |= BIT_ULL(ALSA_SNDIF_FORMATS[i].sndif); return mask; } @@ -208,7 +208,7 @@ static u64 to_alsa_formats_mask(u64 sndif_formats) mask = 0; for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++) - if (1 << ALSA_SNDIF_FORMATS[i].sndif & sndif_formats) + if (BIT_ULL(ALSA_SNDIF_FORMATS[i].sndif) & sndif_formats) mask |= pcm_format_to_bits(ALSA_SNDIF_FORMATS[i].alsa); return mask; From 76864868dbab0bfd9aadaa9155acfe396f8069e4 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 28 Jun 2019 14:53:30 +0900 Subject: [PATCH 529/626] ALSA: firewire-lib: cache next data_block_counter after probing tracepoints event for IR context For debugging purpose, ALSA IEC 61883-1/6 engine has tracepoints event. In current implementation, next data block counter is stored as current data block counter before probing the event for IR isoc context. It's not good to check current packet parameter. This commit changes to assign the next data block counter after probing the event. Besides, Fireworks devices has a quirk to transfer isoc packet with data block counter for the last data block. For this quirk, the assignment is done before calling data block processing layer. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 48 +++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 3aef6a78a188..b341bd86605e 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -519,13 +519,13 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, unsigned int payload_length, - unsigned int *data_blocks, unsigned int *syt) + unsigned int *data_blocks, unsigned int *dbc, + unsigned int *syt) { u32 cip_header[2]; unsigned int sph; unsigned int fmt; unsigned int fdf; - unsigned int data_block_counter; bool lost; cip_header[0] = be32_to_cpu(buf[0]); @@ -577,17 +577,17 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, } /* Check data block counter continuity */ - data_block_counter = cip_header[0] & CIP_DBC_MASK; + *dbc = cip_header[0] & CIP_DBC_MASK; if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && s->data_block_counter != UINT_MAX) - data_block_counter = s->data_block_counter; + *dbc = s->data_block_counter; if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && - data_block_counter == s->ctx_data.tx.first_dbc) || + *dbc == s->ctx_data.tx.first_dbc) || s->data_block_counter == UINT_MAX) { lost = false; } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { - lost = data_block_counter != s->data_block_counter; + lost = *dbc != s->data_block_counter; } else { unsigned int dbc_interval; @@ -596,26 +596,18 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, else dbc_interval = *data_blocks; - lost = data_block_counter != - ((s->data_block_counter + dbc_interval) & 0xff); + lost = *dbc != ((s->data_block_counter + dbc_interval) & 0xff); } if (lost) { dev_err(&s->unit->device, "Detect discontinuity of CIP: %02X %02X\n", - s->data_block_counter, data_block_counter); + s->data_block_counter, *dbc); return -EIO; } *syt = cip_header[1] & CIP_SYT_MASK; - if (s->flags & CIP_DBC_IS_END_EVENT) { - s->data_block_counter = data_block_counter; - } else { - s->data_block_counter = - (data_block_counter + *data_blocks) & 0xff; - } - return 0; } @@ -626,6 +618,7 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, unsigned int *syt, unsigned int index) { const __be32 *cip_header; + unsigned int dbc; int err; *payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; @@ -640,22 +633,33 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, if (!(s->flags & CIP_NO_HEADER)) { cip_header = ctx_header + 2; err = check_cip_header(s, cip_header, *payload_length, - data_blocks, syt); - if (err < 0) - return err; + data_blocks, &dbc, syt); + if (err < 0) { + if (err != -EAGAIN) + return err; + + *data_blocks = 0; + dbc = s->data_block_counter; + } } else { cip_header = NULL; + err = 0; *data_blocks = *payload_length / sizeof(__be32) / s->data_block_quadlets; + dbc = s->data_block_counter; *syt = 0; - s->data_block_counter = - (s->data_block_counter + *data_blocks) & 0xff; } + if (err >= 0 && s->flags & CIP_DBC_IS_END_EVENT) + s->data_block_counter = dbc; + trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, index); - return 0; + if (err >= 0 && !(s->flags & CIP_DBC_IS_END_EVENT)) + s->data_block_counter = (dbc + *data_blocks) & 0xff; + + return err; } // In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On From 973b059ca98054f9400562ae90bea5069b9b9274 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 28 Jun 2019 14:53:31 +0900 Subject: [PATCH 530/626] ALSA: firewire-lib: fix to process MIDI conformant data channel for AM824 format In IEC 61883-6, 8 MIDI data streams are multiplexed into single MIDI conformant data channel. The index of stream is calculated by modulo 8 of the value of data block counter. Therefore data block processing layer requires valid value of data block counter. In recent changes of ALSA IEC 61883-1/6 engine, the value of data block counter is changed before calling data block processing layer. This brings miss detection of MIDI messages in non-blocking transmission method is used. This commit fixes the bug by changing chached data block counter after calling data block processing layer. Fixes: e335425b6596 ("ALSA: firewire-lib: split helper function to check incoming CIP header") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index b341bd86605e..91b890241840 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -614,11 +614,10 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, const __be32 *ctx_header, unsigned int *payload_length, - unsigned int *data_blocks, + unsigned int *data_blocks, unsigned int *dbc, unsigned int *syt, unsigned int index) { const __be32 *cip_header; - unsigned int dbc; int err; *payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; @@ -633,32 +632,28 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, if (!(s->flags & CIP_NO_HEADER)) { cip_header = ctx_header + 2; err = check_cip_header(s, cip_header, *payload_length, - data_blocks, &dbc, syt); + data_blocks, dbc, syt); if (err < 0) { if (err != -EAGAIN) return err; *data_blocks = 0; - dbc = s->data_block_counter; } } else { cip_header = NULL; err = 0; *data_blocks = *payload_length / sizeof(__be32) / s->data_block_quadlets; - dbc = s->data_block_counter; + *dbc = s->data_block_counter; *syt = 0; } if (err >= 0 && s->flags & CIP_DBC_IS_END_EVENT) - s->data_block_counter = dbc; + s->data_block_counter = *dbc; trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, index); - if (err >= 0 && !(s->flags & CIP_DBC_IS_END_EVENT)) - s->data_block_counter = (dbc + *data_blocks) & 0xff; - return err; } @@ -761,7 +756,8 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; i++) { u32 cycle; unsigned int payload_length; - unsigned int data_block; + unsigned int data_blocks; + unsigned int dbc; unsigned int syt; __be32 *buffer; unsigned int pcm_frames = 0; @@ -771,13 +767,19 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, cycle = compute_cycle_count(ctx_header[1]); err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, - &data_block, &syt, i); + &data_blocks, &dbc, &syt, i); if (err < 0 && err != -EAGAIN) break; + if (err >= 0) { buffer = s->buffer.packets[s->packet_index].buffer; pcm_frames = s->process_data_blocks(s, buffer, - data_block, &syt); + data_blocks, &syt); + + if (!(s->flags & CIP_DBC_IS_END_EVENT)) { + s->data_block_counter = + (dbc + data_blocks) & 0xff; + } } if (queue_in_packet(s, ¶ms) < 0) From bc0a5f43d7d6ba5258a65cf00fa692845f128d3c Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Thu, 27 Jun 2019 15:02:07 +0300 Subject: [PATCH 531/626] ASoC: codecs: ad193x: Group register initialization at probe Create a structure with the register initialization values at probe and use it to initialize all the registers at once. Signed-off-by: Codrin Ciubotariu Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 52 +++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 05f4514048e2..f3bab8fe3579 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -415,6 +415,38 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = { .ops = &ad193x_dai_ops, }; +struct ad193x_reg_default { + unsigned int reg; + unsigned int val; +}; + +/* codec register values to set after reset */ +static void ad193x_reg_default_init(struct ad193x_priv *ad193x) +{ + const struct ad193x_reg_default reg_init[] = { + { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ + { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ + { 2, 0x40 }, /* DAC_CTRL0: TDM mode */ + { 4, 0x1A }, /* DAC_CTRL2: 48kHz de-emphasis, unmute dac */ + { 5, 0x00 }, /* DAC_CHNL_MUTE: unmute DAC channels */ + }; + const struct ad193x_reg_default reg_adc_init[] = { + { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ + { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ + }; + int i; + + for (i = 0; i < ARRAY_SIZE(reg_init); i++) + regmap_write(ad193x->regmap, reg_init[i].reg, reg_init[i].val); + + if (ad193x_has_adc(ad193x)) { + for (i = 0; i < ARRAY_SIZE(reg_adc_init); i++) { + regmap_write(ad193x->regmap, reg_adc_init[i].reg, + reg_adc_init[i].val); + } + } +} + static int ad193x_component_probe(struct snd_soc_component *component) { struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component); @@ -422,25 +454,7 @@ static int ad193x_component_probe(struct snd_soc_component *component) int num, ret; /* default setting for ad193x */ - - /* unmute dac channels */ - regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0); - /* de-emphasis: 48kHz, powedown dac */ - regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); - /* dac in tdm mode */ - regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40); - - /* adc only */ - if (ad193x_has_adc(ad193x)) { - /* high-pass filter enable */ - regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); - /* sata delay=1, adc aux mode */ - regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43); - } - - /* pll input: mclki/xi */ - regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ - regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); + ad193x_reg_default_init(ad193x); /* adc only */ if (ad193x_has_adc(ad193x)) { From 8af6b2291e054773e2e58b2e5dbc06e981d14296 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Thu, 27 Jun 2019 15:02:08 +0300 Subject: [PATCH 532/626] ASoC: codecs: ad193x: Reset used registers at probe Since the ad193x codecs have no software reset, we have to reinitialize the registers after a hardware reset to assure no previous values are kept. Signed-off-by: Codrin Ciubotariu Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index f3bab8fe3579..9615e786d049 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -427,12 +427,22 @@ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ { 2, 0x40 }, /* DAC_CTRL0: TDM mode */ + { 3, 0x00 }, /* DAC_CTRL1: reset */ { 4, 0x1A }, /* DAC_CTRL2: 48kHz de-emphasis, unmute dac */ { 5, 0x00 }, /* DAC_CHNL_MUTE: unmute DAC channels */ + { 6, 0x00 }, /* DAC_L1_VOL: no attenuation */ + { 7, 0x00 }, /* DAC_R1_VOL: no attenuation */ + { 8, 0x00 }, /* DAC_L2_VOL: no attenuation */ + { 9, 0x00 }, /* DAC_R2_VOL: no attenuation */ + { 10, 0x00 }, /* DAC_L3_VOL: no attenuation */ + { 11, 0x00 }, /* DAC_R3_VOL: no attenuation */ + { 12, 0x00 }, /* DAC_L4_VOL: no attenuation */ + { 13, 0x00 }, /* DAC_R4_VOL: no attenuation */ }; const struct ad193x_reg_default reg_adc_init[] = { { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ + { 16, 0x00 }, /* ADC_CTRL2: reset */ }; int i; From af18b13fedae4637b439d1265038b30929ca5a4c Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 27 Jun 2019 14:13:49 +0200 Subject: [PATCH 533/626] ASoC: soc-core: defer card registration if codec component is missing Like cpus and platforms, defer sound card initialization if the codec component is missing when initializing the dai_link Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 05cd710273b6..b5f3c09311c3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1071,12 +1071,20 @@ static int soc_init_dai_link(struct snd_soc_card *card, link->name); return -EINVAL; } + /* Codec DAI name must be specified */ if (!codec->dai_name) { dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n", link->name); return -EINVAL; } + + /* + * Defer card registration if codec component is not added to + * component list. + */ + if (!soc_find_component(codec)) + return -EPROBE_DEFER; } /* From 34614739988ad60c3493da66dd856002ee93edf9 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 27 Jun 2019 14:13:50 +0200 Subject: [PATCH 534/626] ASoC: soc-core: support dai_link with platforms_num != 1 Add support platforms_num != 1 in dai_link. Initially, the main purpose of this change was to make the platform optional in the dai_link, instead of inserting the dummy platform driver. This particular case had just been solved by Kuninori Morimoto with commit 1d7689892878 ("ASoC: soc-core: allow no Platform on dai_link"). However, this change may still be useful for those who need multiple platform components on a single dai_link (it solves one of the FIXME note in soc-core) Acked-by: Kuninori Morimoto Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- include/sound/soc.h | 6 +++++ sound/soc/soc-core.c | 59 ++++++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 64405cdab8bb..4e8071269639 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -997,6 +997,12 @@ struct snd_soc_dai_link { ((i) < link->num_codecs) && ((codec) = &link->codecs[i]); \ (i)++) +#define for_each_link_platforms(link, i, platform) \ + for ((i) = 0; \ + ((i) < link->num_platforms) && \ + ((platform) = &link->platforms[i]); \ + (i)++) + /* * Sample 1 : Single CPU/Codec/Platform * diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b5f3c09311c3..b9061cd8d787 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -896,7 +896,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { struct snd_soc_pcm_runtime *rtd; - struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *codec, *platform; struct snd_soc_component *component; int i; @@ -926,13 +926,14 @@ static int soc_bind_dai_link(struct snd_soc_card *card, /* Find CODEC from registered CODECs */ rtd->num_codecs = dai_link->num_codecs; - for_each_link_codecs(dai_link, i, codecs) { - rtd->codec_dais[i] = snd_soc_find_dai(codecs); + for_each_link_codecs(dai_link, i, codec) { + rtd->codec_dais[i] = snd_soc_find_dai(codec); if (!rtd->codec_dais[i]) { dev_info(card->dev, "ASoC: CODEC DAI %s not registered\n", - codecs->dai_name); + codec->dai_name); goto _err_defer; } + snd_soc_rtdcom_add(rtd, rtd->codec_dais[i]->component); } @@ -940,12 +941,13 @@ static int soc_bind_dai_link(struct snd_soc_card *card, rtd->codec_dai = rtd->codec_dais[0]; /* Find PLATFORM from registered PLATFORMs */ - for_each_component(component) { - if (!snd_soc_is_matching_component(dai_link->platforms, - component)) - continue; + for_each_link_platforms(dai_link, i, platform) { + for_each_component(component) { + if (!snd_soc_is_matching_component(platform, component)) + continue; - snd_soc_rtdcom_add(rtd, component); + snd_soc_rtdcom_add(rtd, component); + } } soc_add_pcm_runtime(card, rtd); @@ -1058,15 +1060,14 @@ static int soc_init_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) { int i; - struct snd_soc_dai_link_component *codec; + struct snd_soc_dai_link_component *codec, *platform; for_each_link_codecs(link, i, codec) { /* * Codec must be specified by 1 of name or OF node, * not both or neither. */ - if (!!codec->name == - !!codec->of_node) { + if (!!codec->name == !!codec->of_node) { dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n", link->name); return -EINVAL; @@ -1087,36 +1088,24 @@ static int soc_init_dai_link(struct snd_soc_card *card, return -EPROBE_DEFER; } - /* - * Platform may be specified by either name or OF node, - * or no Platform. - * - * FIXME - * - * We need multi-platform support - */ - if (link->num_platforms > 0) { - - if (link->num_platforms > 1) { + for_each_link_platforms(link, i, platform) { + /* + * Platform may be specified by either name or OF node, but it + * can be left unspecified, then no components will be inserted + * in the rtdcom list + */ + if (!!platform->name == !!platform->of_node) { dev_err(card->dev, - "ASoC: multi platform is not yet supported %s\n", - link->name); - return -EINVAL; - } - - if (link->platforms->name && link->platforms->of_node) { - dev_err(card->dev, - "ASoC: Both platform name/of_node are set for %s\n", + "ASoC: Neither/both platform name/of_node are set for %s\n", link->name); return -EINVAL; } /* - * Defer card registartion if platform dai component is not - * added to component list. + * Defer card registration if platform component is not added to + * component list. */ - if ((link->platforms->of_node || link->platforms->name) && - !soc_find_component(link->platforms)) + if (!soc_find_component(platform)) return -EPROBE_DEFER; } From 8fc22fa4b2cd983e4c542d1841b3d2212ad18ed4 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 28 Jun 2019 10:17:08 +0200 Subject: [PATCH 535/626] ASoC: meson: axg-card: remove useless check on codec While checking cpus before dereferencing the pointer is required, it is not necessary for codecs. 'codec' can't possibly be NULL in the loop Reported-by: Dan Carpenter Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 70bb0cbad233..14a8321744da 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -118,8 +118,7 @@ static void axg_card_clean_references(struct axg_card *priv) if (link->cpus) of_node_put(link->cpus->of_node); for_each_link_codecs(link, j, codec) - if (codec) - of_node_put(codec->of_node); + of_node_put(codec->of_node); } } From 8af26493c03581ad476a77630502de6152cf013d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 13:07:05 +0900 Subject: [PATCH 536/626] ASoC: atmel: atmel-pcm-dma.c: use devm_snd_dmaengine_pcm_register() We have devm_xxx version of snd_dmaengine_pcm_register, let's use it. This patch also removes related empty functions Signed-off-by: Kuninori Morimoto Reviewed-by: Codrin Ciubotariu Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-pcm-dma.c | 9 ++------- sound/soc/atmel/atmel-pcm-pdc.c | 5 ----- sound/soc/atmel/atmel-pcm.h | 8 -------- sound/soc/atmel/atmel_ssc_dai.c | 11 ----------- 4 files changed, 2 insertions(+), 31 deletions(-) diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index 042e59309bcd..db67f5ba1e9a 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c @@ -111,16 +111,11 @@ static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = { int atmel_pcm_dma_platform_register(struct device *dev) { - return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config, 0); + return devm_snd_dmaengine_pcm_register(dev, + &atmel_dmaengine_pcm_config, 0); } EXPORT_SYMBOL(atmel_pcm_dma_platform_register); -void atmel_pcm_dma_platform_unregister(struct device *dev) -{ - snd_dmaengine_pcm_unregister(dev); -} -EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister); - MODULE_AUTHOR("Bo Shen "); MODULE_DESCRIPTION("Atmel DMA based PCM module"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c index 7e9aa7003305..ed095af866db 100644 --- a/sound/soc/atmel/atmel-pcm-pdc.c +++ b/sound/soc/atmel/atmel-pcm-pdc.c @@ -393,11 +393,6 @@ int atmel_pcm_pdc_platform_register(struct device *dev) } EXPORT_SYMBOL(atmel_pcm_pdc_platform_register); -void atmel_pcm_pdc_platform_unregister(struct device *dev) -{ -} -EXPORT_SYMBOL(atmel_pcm_pdc_platform_unregister); - MODULE_AUTHOR("Sedji Gaouaou "); MODULE_DESCRIPTION("Atmel PCM module"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h index 5173c9b529ba..2e648748e5cb 100644 --- a/sound/soc/atmel/atmel-pcm.h +++ b/sound/soc/atmel/atmel-pcm.h @@ -72,28 +72,20 @@ struct atmel_pcm_dma_params { #if IS_ENABLED(CONFIG_SND_ATMEL_SOC_PDC) int atmel_pcm_pdc_platform_register(struct device *dev); -void atmel_pcm_pdc_platform_unregister(struct device *dev); #else static inline int atmel_pcm_pdc_platform_register(struct device *dev) { return 0; } -static inline void atmel_pcm_pdc_platform_unregister(struct device *dev) -{ -} #endif #if IS_ENABLED(CONFIG_SND_ATMEL_SOC_DMA) int atmel_pcm_dma_platform_register(struct device *dev); -void atmel_pcm_dma_platform_unregister(struct device *dev); #else static inline int atmel_pcm_dma_platform_register(struct device *dev) { return 0; } -static inline void atmel_pcm_dma_platform_unregister(struct device *dev) -{ -} #endif #endif /* _ATMEL_PCM_H */ diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index b66c7789d096..6f89483ac88c 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -1012,16 +1012,6 @@ static int asoc_ssc_init(struct device *dev) return 0; } -static void asoc_ssc_exit(struct device *dev) -{ - struct ssc_device *ssc = dev_get_drvdata(dev); - - if (ssc->pdata->use_dma) - atmel_pcm_dma_platform_unregister(dev); - else - atmel_pcm_pdc_platform_unregister(dev); -} - /** * atmel_ssc_set_audio - Allocate the specified SSC for audio use. */ @@ -1050,7 +1040,6 @@ void atmel_ssc_put_audio(int ssc_id) { struct ssc_device *ssc = ssc_info[ssc_id].ssc; - asoc_ssc_exit(&ssc->pdev->dev); ssc_free(ssc); } EXPORT_SYMBOL_GPL(atmel_ssc_put_audio); From 1ad741d0e8e8ecccc16aa9ccb8362575197d91bf Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 27 Jun 2019 14:32:08 +0100 Subject: [PATCH 537/626] ASoC: topology: fix memory leaks on sm, se and sbe Currently when a kstrdup fails the error exit paths don't free the allocations for sm, se and sbe. This can be fixed by assigning kc[i].private_value to these before doing the ksrtdup so that the error exit path will be able to free these objects. Addresses-Coverity: ("Resource leak") Fixes: 9f90af3a9952 ("ASoC: topology: Consolidate and fix asoc_tplg_dapm_widget_*_create flow") Signed-off-by: Colin Ian King Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index fc1f1d6f9e92..dc463f1a9e24 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1326,10 +1326,10 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( dev_dbg(tplg->dev, " adding DAPM widget mixer control %s at %d\n", mc->hdr.name, i); + kc[i].private_value = (long)sm; kc[i].name = kstrdup(mc->hdr.name, GFP_KERNEL); if (kc[i].name == NULL) goto err_sm; - kc[i].private_value = (long)sm; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc[i].access = mc->hdr.access; @@ -1412,10 +1412,10 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n", ec->hdr.name); + kc[i].private_value = (long)se; kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL); if (kc[i].name == NULL) goto err_se; - kc[i].private_value = (long)se; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc[i].access = ec->hdr.access; @@ -1524,10 +1524,10 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( "ASoC: adding bytes kcontrol %s with access 0x%x\n", be->hdr.name, be->hdr.access); + kc[i].private_value = (long)sbe; kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL); if (kc[i].name == NULL) goto err_sbe; - kc[i].private_value = (long)sbe; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc[i].access = be->hdr.access; From 8a90efd15ef6472809374aea963927dcba2bfc03 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:46:14 +0900 Subject: [PATCH 538/626] ASoC: vc4: vc4_htmi: consider CPU-Platform possibility commit 6c6de1c9e2bf2 ("ASoC: vc4: vc4_hdmi: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 6c6de1c9e2bf2 ("ASoC: vc4: vc4_hdmi: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 869084167822..9f385979d1e6 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -60,6 +60,7 @@ struct vc4_hdmi_audio { struct snd_soc_dai_link link; struct snd_soc_dai_link_component cpu; struct snd_soc_dai_link_component codec; + struct snd_soc_dai_link_component platform; int samplerate; int channels; struct snd_dmaengine_dai_dma_data dma_data; @@ -1089,15 +1090,18 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi) dai_link->cpus = &hdmi->audio.cpu; dai_link->codecs = &hdmi->audio.codec; + dai_link->platforms = &hdmi->audio.platform; dai_link->num_cpus = 1; dai_link->num_codecs = 1; + dai_link->num_platforms = 1; dai_link->name = "MAI"; dai_link->stream_name = "MAI PCM"; dai_link->codecs->dai_name = vc4_hdmi_audio_codec_dai_drv.name; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = dev_name(dev); + dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From ca1c67d1603a8702792c8bf984b169ccb1a72718 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:46:19 +0900 Subject: [PATCH 539/626] ASoC: atmel: atmel-classd: consider CPU-Platform possibility commit 02602401e5316 ("ASoC: atmel: atmel-classd: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 02602401e5316 ("ASoC: atmel: atmel-classd: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index a2390e9b97c7..0f2c574f27f1 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -503,21 +503,24 @@ static int atmel_classd_asoc_card_init(struct device *dev, if (!dai_link) return -ENOMEM; - comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; dai_link->cpus = &comp[0]; dai_link->codecs = &comp[1]; + dai_link->platforms = &comp[2]; dai_link->num_cpus = 1; dai_link->num_codecs = 1; + dai_link->num_platforms = 1; dai_link->name = "CLASSD"; dai_link->stream_name = "CLASSD PCM"; dai_link->codecs->dai_name = ATMEL_CLASSD_CODEC_DAI_NAME; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = dev_name(dev); + dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From ea2d1868c4841423e0eb658f3f5747c7513c9187 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:46:24 +0900 Subject: [PATCH 540/626] ASoC: atmel: atmel-pdmic: consider CPU-Platform possibility commit 7baf32e164da5d4 ("ASoC: atmel: atmel-pdmic: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 7baf32e164da5d4 ("ASoC: atmel: atmel-pdmic: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-pdmic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index d46741003fa8..e09c28349e0d 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -514,21 +514,24 @@ static int atmel_pdmic_asoc_card_init(struct device *dev, if (!dai_link) return -ENOMEM; - comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; dai_link->cpus = &comp[0]; dai_link->codecs = &comp[1]; + dai_link->platforms = &comp[2]; dai_link->num_cpus = 1; dai_link->num_codecs = 1; + dai_link->num_platforms = 1; dai_link->name = "PDMIC"; dai_link->stream_name = "PDMIC PCM"; dai_link->codecs->dai_name = ATMEL_PDMIC_CODEC_DAI_NAME; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = dev_name(dev); + dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From 16589b77a95668b0046658188ea55684709768c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:46:37 +0900 Subject: [PATCH 541/626] ASoC: atmel: atmel_wm8904: consider CPU-Platform possibility unnecessary Platform" commit 3609750e9d4ba9db ("ASoC: atmel: atmel_wm8904: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 3609750e9d4ba9db ("ASoC: atmel: atmel_wm8904: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_wm8904.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index 84e5e5da5619..776b27d3686e 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c @@ -58,7 +58,8 @@ static const struct snd_soc_ops atmel_asoc_wm8904_ops = { SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8904-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8904-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { .name = "WM8904", @@ -112,6 +113,7 @@ static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev) return ret; } dailink->cpus->of_node = cpu_np; + dailink->platforms->of_node = cpu_np; of_node_put(cpu_np); codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); From 716407ea57fa38fc1b04c699f1b83847cf669872 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:46:49 +0900 Subject: [PATCH 542/626] ASoC: amtel: mikroe-proto: consider CPU-Platform possibility commit 318ebbe8060d96 ("ASoC: atmel: mikroe-proto: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 318ebbe8060d96 ("ASoC: atmel: mikroe-proto: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/mikroe-proto.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/atmel/mikroe-proto.c b/sound/soc/atmel/mikroe-proto.c index 954b24e23730..aa6d0d78566f 100644 --- a/sound/soc/atmel/mikroe-proto.c +++ b/sound/soc/atmel/mikroe-proto.c @@ -85,8 +85,8 @@ static int snd_proto_probe(struct platform_device *pdev) if (!dai) return -ENOMEM; - /* for cpus/codecs */ - comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); + /* for cpus/codecs/platforms */ + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; @@ -97,6 +97,8 @@ static int snd_proto_probe(struct platform_device *pdev) dai->num_cpus = 1; dai->codecs = &comp[1]; dai->num_codecs = 1; + dai->platforms = &comp[2]; + dai->num_platforms = 1; dai->name = "WM8731"; dai->stream_name = "WM8731 HiFi"; @@ -116,6 +118,7 @@ static int snd_proto_probe(struct platform_device *pdev) return -EINVAL; } dai->cpus->of_node = cpu_np; + dai->platforms->of_node = cpu_np; dai_fmt = snd_soc_of_parse_daifmt(np, NULL, &bitclkmaster, &framemaster); From 0efd1d7cbcc5f5be4025fc6cd2809e50c3030f09 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:02 +0900 Subject: [PATCH 543/626] ASoC: atmel: sam9g20_wm8731: consider CPU-Platform possibility commit bfc7938e58142a5 ("ASoC: atmel: sam9g20_wm8731: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit bfc7938e58142a5 ("ASoC: atmel: sam9g20_wm8731: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/sam9g20_wm8731.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index df098d3cf844..b1bef2bf142d 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -118,7 +118,8 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_CPU("at91rm9200_ssc.0")), - DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("at91rm9200_ssc.0"))); static struct snd_soc_dai_link at91sam9g20ek_dai = { .name = "WM8731", @@ -209,12 +210,14 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev) /* Parse dai and platform info */ at91sam9g20ek_dai.cpus->dai_name = NULL; + at91sam9g20ek_dai.platforms->name = NULL; cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); if (!cpu_np) { dev_err(&pdev->dev, "dai and pcm info missing\n"); return -EINVAL; } at91sam9g20ek_dai.cpus->of_node = cpu_np; + at91sam9g20ek_dai.platforms->of_node = cpu_np; of_node_put(codec_np); of_node_put(cpu_np); From e1be6aa0984e8b3d1aeccda527360f9c7c9ff54f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:06 +0900 Subject: [PATCH 544/626] ASoC: atmel: sam9x5_wm8731: consider CPU-Platform possibility commit ced5b08020cd ("ASoC: atmel: sam9x5_wm8731: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit ced5b08020cd ("ASoC: atmel: sam9x5_wm8731: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/sam9x5_wm8731.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index d2dc344ff0a8..7822425d5e61 100644 --- a/sound/soc/atmel/sam9x5_wm8731.c +++ b/sound/soc/atmel/sam9x5_wm8731.c @@ -88,7 +88,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); if (!dai || !card || !priv || !comp) { ret = -ENOMEM; goto out; @@ -107,6 +107,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) dai->num_cpus = 1; dai->codecs = &comp[1]; dai->num_codecs = 1; + dai->platforms = &comp[2]; + dai->num_platforms = 1; dai->name = "WM8731"; dai->stream_name = "WM8731 PCM"; @@ -143,6 +145,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) goto out; } dai->cpus->of_node = cpu_np; + dai->platforms->of_node = cpu_np; priv->ssc_id = of_alias_get_id(cpu_np, "ssc"); From 6910bb935a448f3af64bf4ab7754cc0870590146 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:10 +0900 Subject: [PATCH 545/626] ASoC: atmel: tse850-pcm5142: consider CPU-Platform possibility commit 655368dfc75e8 ("ASoC: atmel: tse850-pcm5142: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 655368dfc75e8 ("ASoC: atmel: tse850-pcm5142: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/tse850-pcm5142.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index 319acb1676c7..59e2edb22b3a 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -296,7 +296,8 @@ static const struct snd_soc_dapm_route tse850_intercon[] = { SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tse850_dailink = { .name = "TSE-850", @@ -336,6 +337,7 @@ static int tse850_dt_init(struct platform_device *pdev) return -EINVAL; } dailink->cpus->of_node = cpu_np; + dailink->platforms->of_node = cpu_np; of_node_put(cpu_np); codec_np = of_parse_phandle(np, "axentia,audio-codec", 0); From 68707c37017086c51b319098afb2cf6d6853ef57 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:14 +0900 Subject: [PATCH 546/626] ASoC: fsl: eukrea-tlv320: consider CPU-Platform possibility commit 2058ea1c4f514a ("ASoC: fsl: eukrea-tlv320: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 2058ea1c4f514a ("ASoC: fsl: eukrea-tlv320: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/eukrea-tlv320.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 1ed409d423c3..6f3b768489f6 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -63,7 +63,8 @@ static const struct snd_soc_ops eukrea_tlv320_snd_ops = { SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", @@ -133,8 +134,10 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) ext_port--; eukrea_tlv320_dai.cpus->of_node = ssi_np; + eukrea_tlv320_dai.platforms->of_node = ssi_np; } else { eukrea_tlv320_dai.cpus->dai_name = "imx-ssi.0"; + eukrea_tlv320_dai.platforms->name = "imx-ssi.0"; eukrea_tlv320_dai.codecs->name = "tlv320aic23-codec.0-001a"; eukrea_tlv320.name = "cpuimx-audio"; } From 9998d3e2add865723a4dffabaa0a8c12c7ee589b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:18 +0900 Subject: [PATCH 547/626] ASoC: fsl: fsl-asoc-card: consider CPU-Platform possibility commit e57a4c2f15df27 ("ASoC: fsl: fsl-asoc-card: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit e57a4c2f15df27 ("ASoC: fsl: fsl-asoc-card: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 55a7e09170fb..39ea9bda1394 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -201,12 +201,14 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, } SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(hifi_fe, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_DUMMY())); + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(hifi_be, DAILINK_COMP_ARRAY(COMP_EMPTY()), @@ -654,12 +656,14 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } } + priv->dai_link[0].platforms->of_node = cpu_np; priv->dai_link[0].dai_fmt = priv->dai_fmt; priv->card.num_links = 1; if (asrc_pdev) { /* DPCM DAI Links only if ASRC exsits */ priv->dai_link[1].cpus->of_node = asrc_np; + priv->dai_link[1].platforms->of_node = asrc_np; priv->dai_link[2].codecs->dai_name = codec_dai_name; priv->dai_link[2].codecs->of_node = codec_np; priv->dai_link[2].codecs->name = From 8bebc822a50a9b5ae3dd88ebec7a3f4872da219c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:22 +0900 Subject: [PATCH 548/626] ASoC: fsl: imx-es8328: consider CPU-Platform possibility commit 577cf50d4dc8 ("ASoC: fsl: imx-es8328: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 577cf50d4dc8 ("ASoC: fsl: imx-es8328: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-es8328.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index 089ee140c718..15a27a2cd0ca 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -148,7 +148,7 @@ static int imx_es8328_probe(struct platform_device *pdev) goto fail; } - comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); if (!comp) { ret = -ENOMEM; goto fail; @@ -160,15 +160,18 @@ static int imx_es8328_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; + data->dai.num_platforms = 1; data->dai.name = "hifi"; data->dai.stream_name = "hifi"; data->dai.codecs->dai_name = "es8328-hifi-analog"; data->dai.codecs->of_node = codec_np; data->dai.cpus->of_node = ssi_np; + data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_es8328_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; From 2b1407c989ec2083fd6aa6d9ae3fa2929e42d471 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:26 +0900 Subject: [PATCH 549/626] ASoC: fsl: imx-sgtl5000: consider CPU-Platform possibility commit 82bf78ca49a3 ("ASoC: fsl: imx-sgtl5000: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 82bf78ca49a3 ("ASoC: fsl: imx-sgtl5000: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-sgtl5000.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index c5ebe4950567..15e8b9343c35 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -123,7 +123,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) goto fail; } - comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); if (!comp) { ret = -ENOMEM; goto fail; @@ -139,15 +139,18 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; + data->dai.num_platforms = 1; data->dai.name = "HiFi"; data->dai.stream_name = "HiFi"; data->dai.codecs->dai_name = "sgtl5000"; data->dai.codecs->of_node = codec_np; data->dai.cpus->of_node = ssi_np; + data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_sgtl5000_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; From 9e8f5299c99518e10cb864c2ad62683507d71c21 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:30 +0900 Subject: [PATCH 550/626] ASoC: fsl: imx-spdif: consider CPU-Platform possibility commit 014f07ca1cb12 ("ASoC: fsl: imx-spdif: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 014f07ca1cb12 ("ASoC: fsl: imx-spdif: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-spdif.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 393c5a31f494..6c4dadf60355 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,7 +26,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); if (!data || !comp) { ret = -ENOMEM; goto end; @@ -34,15 +34,18 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; + data->dai.num_platforms = 1; data->dai.name = "S/PDIF PCM"; data->dai.stream_name = "S/PDIF PCM"; data->dai.codecs->dai_name = "snd-soc-dummy-dai"; data->dai.codecs->name = "snd-soc-dummy"; data->dai.cpus->of_node = spdif_np; + data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; From 9213866ac48fbe1f76211b5e539ef4e0011ddd0d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:35 +0900 Subject: [PATCH 551/626] ASoC: fsl: imx-audmix: consider CPU-Platform possibility commit d8893261a7d32 ("ASoC: fsl: imx-audmix: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit d8893261a7d32 ("ASoC: fsl: imx-audmix: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 9d41266a5264..9e1cb18859ce 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec x 2 */ - dlc = devm_kzalloc(&pdev->dev, 4 * sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec/Platform x 2 */ + dlc = devm_kzalloc(&pdev->dev, 6 * sizeof(*dlc), GFP_KERNEL); if (!dlc) { dev_err(&pdev->dev, "failed to allocate dai_link\n"); return -ENOMEM; @@ -242,9 +242,11 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].cpus = &dlc[0]; priv->dai[i].codecs = &dlc[1]; + priv->dai[i].platforms = &dlc[2]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; + priv->dai[i].num_platforms = 1; priv->dai[i].name = dai_name; priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; @@ -252,6 +254,7 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].codecs->name = "snd-soc-dummy"; priv->dai[i].cpus->of_node = args.np; priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); + priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -266,17 +269,20 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); - priv->dai[num_dai + i].cpus = &dlc[2]; - priv->dai[num_dai + i].codecs = &dlc[3]; + priv->dai[num_dai + i].cpus = &dlc[3]; + priv->dai[num_dai + i].codecs = &dlc[4]; + priv->dai[num_dai + i].platforms = &dlc[5]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; + priv->dai[num_dai + i].num_platforms = 1; priv->dai[num_dai + i].name = be_name; priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; priv->dai[num_dai + i].cpus->of_node = audmix_np; priv->dai[num_dai + i].cpus->dai_name = be_name; + priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; From bb6630d153a16e0cde1e849fcf298d8fec0e77bb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:38 +0900 Subject: [PATCH 552/626] ASoC: kirkwood: armada-370-db: consider CPU-Platform possibility commit 717f16331712 ("ASoC: kirkwood: armada-370-db: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 717f16331712 ("ASoC: kirkwood: armada-370-db: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/kirkwood/armada-370-db.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c index fcf84a54ad16..8c3c808bda9a 100644 --- a/sound/soc/kirkwood/armada-370-db.c +++ b/sound/soc/kirkwood/armada-370-db.c @@ -56,15 +56,18 @@ static const struct snd_soc_dapm_route a370db_route[] = { SND_SOC_DAILINK_DEFS(analog, DAILINK_COMP_ARRAY(COMP_CPU("i2s")), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42l51-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42l51-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(spdif_out, DAILINK_COMP_ARRAY(COMP_CPU("spdif")), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dit-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dit-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(spdif_in, DAILINK_COMP_ARRAY(COMP_CPU("spdif")), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dir-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dir-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link a370db_dai[] = { { @@ -108,18 +111,21 @@ static int a370db_probe(struct platform_device *pdev) a370db_dai[0].cpus->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-controller", 0); + a370db_dai[0].platforms->of_node = a370db_dai[0].cpus->of_node; a370db_dai[0].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-codec", 0); a370db_dai[1].cpus->of_node = a370db_dai[0].cpus->of_node; + a370db_dai[1].platforms->of_node = a370db_dai[0].cpus->of_node; a370db_dai[1].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "marvell,audio-codec", 1); a370db_dai[2].cpus->of_node = a370db_dai[0].cpus->of_node; + a370db_dai[2].platforms->of_node = a370db_dai[0].cpus->of_node; a370db_dai[2].codecs->of_node = of_parse_phandle(pdev->dev.of_node, From 802e8ed9e912281cbfe4432cf015c82b81e87faa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:42 +0900 Subject: [PATCH 553/626] ASoC: mxs: mxs-sgtl5000: consider CPU-Platform possibility commit 5f92229d184b ("ASoC: mxs: mxs-sgtl5000: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 5f92229d184b ("ASoC: mxs: mxs-sgtl5000: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-sgtl5000.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index aa24d0d7c2e8..9841e1da9782 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -65,11 +65,13 @@ static const struct snd_soc_ops mxs_sgtl5000_hifi_ops = { SND_SOC_DAILINK_DEFS(hifi_tx, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(hifi_rx, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { { @@ -124,6 +126,8 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) mxs_sgtl5000_dai[i].codecs->of_node = codec_np; mxs_sgtl5000_dai[i].cpus->dai_name = NULL; mxs_sgtl5000_dai[i].cpus->of_node = saif_np[i]; + mxs_sgtl5000_dai[i].platforms->name = NULL; + mxs_sgtl5000_dai[i].platforms->of_node = saif_np[i]; } of_node_put(codec_np); From 291728a523231f22155610fd595a83bdc91f147b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:46 +0900 Subject: [PATCH 554/626] ASoC: qcom: apq8016_sbc: consider CPU-Platform possibility commit 564684387969 ("ASoC: qcom: apq8016_sbc: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 564684387969 ("ASoC: qcom: apq8016_sbc: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/apq8016_sbc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index c0b0aa8493d3..f60a71990f66 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -150,12 +150,15 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) link = data->dai_link; - dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL); + dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); if (!dlc) return ERR_PTR(-ENOMEM); - link->cpus = dlc; - link->num_cpus = 1; + link->cpus = &dlc[0]; + link->platforms = &dlc[1]; + + link->num_cpus = 1; + link->num_platforms = 1; for_each_child_of_node(node, np) { cpu = of_get_child_by_name(np, "cpu"); @@ -187,6 +190,7 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) goto error; } + link->platforms->of_node = link->cpus->of_node; ret = of_property_read_string(np, "link-name", &link->name); if (ret) { dev_err(card->dev, "error getting codec dai_link name\n"); From 9522e94749d1eb2e88ca4fb1ed20dbbf6ac381d1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:50 +0900 Subject: [PATCH 555/626] ASoC: qcom: storm: consider CPU-Platform possibility commit 3caf11fa88a9 ("ASoC: qcom: storm: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 3caf11fa88a9 ("ASoC: qcom: storm: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/storm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c index e6aeed7b6b97..e6666e597265 100644 --- a/sound/soc/qcom/storm.c +++ b/sound/soc/qcom/storm.c @@ -55,7 +55,8 @@ static const struct snd_soc_ops storm_soc_ops = { SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link storm_dai_link = { .name = "Primary", @@ -74,6 +75,7 @@ static int storm_parse_of(struct snd_soc_card *card) dev_err(card->dev, "error getting cpu phandle\n"); return -EINVAL; } + dai_link->platforms->of_node = dai_link->cpus->of_node; dai_link->codecs->of_node = of_parse_phandle(np, "codec", 0); if (!dai_link->codecs->of_node) { From 418e12fcaa53532aeeaf502dc787eb2a26b11f17 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:54 +0900 Subject: [PATCH 556/626] ASoC: rockchip: rk3288_hdmi_analog: consider CPU-Platform possibility commit 9c21e82c165c ("ASoC: rockchip: rk3288_hdmi_analog: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 9c21e82c165c ("ASoC: rockchip: rk3288_hdmi_analog: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3288_hdmi_analog.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c index 731f75d5dc7d..767700c34ee2 100644 --- a/sound/soc/rockchip/rk3288_hdmi_analog.c +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c @@ -142,7 +142,8 @@ static const struct snd_soc_ops rk_ops = { SND_SOC_DAILINK_DEFS(audio, DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL), - COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi"))); + COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link rk_dailink = { .name = "Codecs", @@ -236,6 +237,8 @@ static int snd_rk_mc_probe(struct platform_device *pdev) return -EINVAL; } + rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; + ret = snd_soc_of_parse_audio_routing(card, "rockchip,routing"); if (ret) { dev_err(&pdev->dev, From 5554af40e8d41ed30a619e730ca86e7e98aabe45 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:47:57 +0900 Subject: [PATCH 557/626] ASoC: rockchip: rockchip_max98090: consider CPU-Platform possibility commit 7df405ae5895 ("ASoC: rockchip: rockchip_max98090: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 7df405ae5895 ("ASoC: rockchip: rockchip_max98090: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index cc08cd874d44..c5fc24675a33 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -113,7 +113,8 @@ static const struct snd_soc_ops rk_aif1_ops = { SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link rk_dailink = { .name = "max98090", @@ -192,6 +193,8 @@ static int snd_rk_mc_probe(struct platform_device *pdev) return -EINVAL; } + rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; + rk_98090_headset_dev.codec_of_node = of_parse_phandle(np, "rockchip,headset-codec", 0); if (!rk_98090_headset_dev.codec_of_node) { From f94d7b6e63b7323e89e9797dbdf6e56a3ec5d490 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:01 +0900 Subject: [PATCH 558/626] ASoC: rockchip: rockchip_rt5645: consider CPU-Platform possibility commit 27a37973a6f1 ("ASoC: rockchip: rockchip_rt5645: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 27a37973a6f1 ("ASoC: rockchip: rockchip_rt5645: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_rt5645.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index fe533726d288..26b67b245484 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -125,7 +125,8 @@ static const struct snd_soc_ops rk_aif1_ops = { SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link rk_dailink = { .name = "rt5645", @@ -177,6 +178,8 @@ static int snd_rk_mc_probe(struct platform_device *pdev) goto put_codec_of_node; } + rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; + ret = snd_soc_of_parse_card_name(card, "rockchip,model"); if (ret) { dev_err(&pdev->dev, From a0e95c4d376d30e50b2b1f4769a6dcc5c7604505 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:15 +0900 Subject: [PATCH 559/626] ASoC: samsung: arndale_rt5631: consider CPU-Platform possibility commit 33949eb5019d ("ASoC: samsung: arndale_rt5631: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 33949eb5019d ("ASoC: samsung: arndale_rt5631: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/arndale_rt5631.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/samsung/arndale_rt5631.c b/sound/soc/samsung/arndale_rt5631.c index e36c140400b7..c213913eb984 100644 --- a/sound/soc/samsung/arndale_rt5631.c +++ b/sound/soc/samsung/arndale_rt5631.c @@ -52,7 +52,8 @@ static struct snd_soc_ops arndale_ops = { SND_SOC_DAILINK_DEFS(rt5631_hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link arndale_rt5631_dai[] = { { @@ -92,6 +93,9 @@ static int arndale_audio_probe(struct platform_device *pdev) return -EINVAL; } } + if (!arndale_rt5631_dai[n].platforms->name) + arndale_rt5631_dai[n].platforms->of_node = + arndale_rt5631_dai[n].cpus->of_node; arndale_rt5631_dai[n].codecs->name = NULL; arndale_rt5631_dai[n].codecs->of_node = of_parse_phandle(np, From 806bfc27ea84e7d934f513b6f4948138c782fb4a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:19 +0900 Subject: [PATCH 560/626] ASoC: samsung: smdk_wm8994: consider CPU-Platform possibility commit d815e0f08fdd ("ASoC: samsung: smdk_wm8994: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit d815e0f08fdd ("ASoC: samsung: smdk_wm8994: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 99aa1620a17d..28f8be000aa1 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -102,11 +102,13 @@ static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(aif1, DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), - DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1"))); + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); SND_SOC_DAILINK_DEFS(fifo_tx, DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s-sec")), - DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1"))); + DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s-sec"))); static struct snd_soc_dai_link smdk_dai[] = { { /* Primary DAI i/f */ @@ -163,6 +165,9 @@ static int smdk_audio_probe(struct platform_device *pdev) "Property 'samsung,i2s-controller' missing or invalid\n"); ret = -EINVAL; } + + smdk_dai[0].platforms->name = NULL; + smdk_dai[0].platforms->of_node = smdk_dai[0].cpus->of_node; } id = of_match_device(of_match_ptr(samsung_wm8994_of_match), &pdev->dev); From 3dfc3e9c24b742067bbcbf849caba294bdb938f6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:23 +0900 Subject: [PATCH 561/626] ASoC: samsung: snow: consider CPU-Platform possibility commit a555b6a959e6 ("ASoC: samsung: snow: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit a555b6a959e6 ("ASoC: samsung: snow: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 7d669c42cdad..8ea7799df028 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -14,9 +14,9 @@ #define FIN_PLL_RATE 24000000 -SND_SOC_DAILINK_DEF(links_cpus, - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEF(links_codecs, +SND_SOC_DAILINK_DEFS(links, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); struct snow_priv { @@ -150,6 +150,8 @@ static int snow_probe(struct platform_device *pdev) link->num_cpus = ARRAY_SIZE(links_cpus); link->codecs = links_codecs; link->num_codecs = ARRAY_SIZE(links_codecs); + link->platforms = links_platforms; + link->num_platforms = ARRAY_SIZE(links_platforms); card->dai_link = link; card->num_links = 1; @@ -205,6 +207,8 @@ static int snow_probe(struct platform_device *pdev) } } + link->platforms->of_node = link->cpus->of_node; + /* Update card-name if provided through DT, else use default name */ snd_soc_of_parse_card_name(card, "samsung,model"); From 74a25f36ba7af991c1133a5ce75d8f0a65ed3c7c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:27 +0900 Subject: [PATCH 562/626] ASoC: samsung: tm2_wm5110: consider CPU-Platform possibility commit ae7cbcc43b8c ("ASoC: samsung: tm2_wm5110: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit ae7cbcc43b8c ("ASoC: samsung: tm2_wm5110: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/samsung/tm2_wm5110.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index a80781031f62..c091033d17ad 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -429,17 +429,21 @@ static struct snd_soc_dai_driver tm2_ext_dai[] = { SND_SOC_DAILINK_DEFS(aif1, DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif1"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(voice, DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif2"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif2")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(bt, DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif3"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif3")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(hdmi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); @@ -572,12 +576,14 @@ static int tm2_probe(struct platform_device *pdev) unsigned int dai_index = 0; /* WM5110 */ dai_link->cpus->name = NULL; + dai_link->platforms->name = NULL; if (num_codecs > 1 && i == card->num_links - 1) dai_index = 1; /* HDMI */ dai_link->codecs->of_node = codec_dai_node[dai_index]; dai_link->cpus->of_node = cpu_dai_node[dai_index]; + dai_link->platforms->of_node = cpu_dai_node[dai_index]; } if (num_codecs > 1) { From e22c32e1d41b69501ab04c1ec865eea606f7ebe2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:31 +0900 Subject: [PATCH 563/626] ASoC: sirf: sirf-audio: consider CPU-Platform possibility commit e562a5f13c94 ("ASoC: sirf: sirf-audio: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit e562a5f13c94 ("ASoC: sirf: sirf-audio: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sirf/sirf-audio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c index 45ad23638bdc..c923b6772b22 100644 --- a/sound/soc/sirf/sirf-audio.c +++ b/sound/soc/sirf/sirf-audio.c @@ -62,7 +62,8 @@ static const struct snd_soc_dapm_route intercon[] = { /* Digital audio interface glue - connects codec <--> CPU */ SND_SOC_DAILINK_DEFS(sirf, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sirf-audio-codec"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sirf-audio-codec")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link sirf_audio_dai_link[] = { { @@ -97,6 +98,8 @@ static int sirf_audio_probe(struct platform_device *pdev) sirf_audio_dai_link[0].cpus->of_node = of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); + sirf_audio_dai_link[0].platforms->of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); sirf_audio_dai_link[0].codecs->of_node = of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0); sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node, From d3569a47663b6feaa2788e885e84afa1c48741e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:35 +0900 Subject: [PATCH 564/626] ASoC: sunxi: sun4i-codec: consider CPU-Platform possibility commit 3f780533bac9 ("ASoC: sunxi: sun4i-codec: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 3f780533bac9 ("ASoC: sunxi: sun4i-codec: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index cd96cf5b01fa..619073e7d972 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1297,21 +1297,24 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, struct snd_soc_dai_link *link = devm_kzalloc(dev, sizeof(*link), GFP_KERNEL); struct snd_soc_dai_link_component *dlc = devm_kzalloc(dev, - 2 * sizeof(*dlc), GFP_KERNEL); + 3 * sizeof(*dlc), GFP_KERNEL); if (!link || !dlc) return NULL; link->cpus = &dlc[0]; link->codecs = &dlc[1]; + link->platforms = &dlc[2]; link->num_cpus = 1; link->num_codecs = 1; + link->num_platforms = 1; link->name = "cdc"; link->stream_name = "CDC PCM"; link->codecs->dai_name = "Codec"; link->cpus->dai_name = dev_name(dev); link->codecs->name = dev_name(dev); + link->platforms->name = dev_name(dev); link->dai_fmt = SND_SOC_DAIFMT_I2S; *num_links = 1; From bae05f2cbf9a8aeaed3408f35759cf1afae3c391 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:40 +0900 Subject: [PATCH 565/626] ASoC: tegra: tegra_alc5632: consider CPU-Platform possibility commit e7fc99e641da ("ASoC: tegra: tegra_alc5632: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit e7fc99e641da ("ASoC: tegra: tegra_alc5632: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 8f689ef2110e..9e8b1497efd3 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -123,7 +123,8 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "alc5632-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "alc5632-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tegra_alc5632_dai = { .name = "ALC5632", @@ -194,6 +195,8 @@ static int tegra_alc5632_probe(struct platform_device *pdev) goto err_put_codec_of_node; } + tegra_alc5632_dai.platforms->of_node = tegra_alc5632_dai.cpus->of_node; + ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev); if (ret) goto err_put_cpu_of_node; @@ -212,6 +215,7 @@ err_fini_utils: err_put_cpu_of_node: of_node_put(tegra_alc5632_dai.cpus->of_node); tegra_alc5632_dai.cpus->of_node = NULL; + tegra_alc5632_dai.platforms->of_node = NULL; err_put_codec_of_node: of_node_put(tegra_alc5632_dai.codecs->of_node); tegra_alc5632_dai.codecs->of_node = NULL; @@ -230,6 +234,7 @@ static int tegra_alc5632_remove(struct platform_device *pdev) of_node_put(tegra_alc5632_dai.cpus->of_node); tegra_alc5632_dai.cpus->of_node = NULL; + tegra_alc5632_dai.platforms->of_node = NULL; of_node_put(tegra_alc5632_dai.codecs->of_node); tegra_alc5632_dai.codecs->of_node = NULL; From abe4918b94b372a9cfe8863b77a48b7ab83d9dd6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:45 +0900 Subject: [PATCH 566/626] ASoC: tegra: tegra_max98090: consider CPU-Platform possibility commit 4bfd08540b44 ("ASoC: tegra: tegra_max98090: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 4bfd08540b44 ("ASoC: tegra: tegra_max98090: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_max98090.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index 4786baaa1388..4954a33ff46b 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c @@ -167,7 +167,8 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tegra_max98090_dai = { .name = "max98090", @@ -241,6 +242,8 @@ static int tegra_max98090_probe(struct platform_device *pdev) goto err; } + tegra_max98090_dai.platforms->of_node = tegra_max98090_dai.cpus->of_node; + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; From ff9194baa91b854ffcec538d4565ecdde40eaf3d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:49 +0900 Subject: [PATCH 567/626] ASoC: tegra: tegra_rt5640: consider CPU-Platform possibility commit 1d641e1523ca ("ASoC: tegra: tegra_rt5640: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 1d641e1523ca ("ASoC: tegra: tegra_rt5640: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_rt5640.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 4ed04689fac1..d46915a3ec4c 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -117,7 +117,8 @@ static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(aif1, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5640-aif1"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5640-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tegra_rt5640_dai = { .name = "RT5640", @@ -187,6 +188,8 @@ static int tegra_rt5640_probe(struct platform_device *pdev) goto err; } + tegra_rt5640_dai.platforms->of_node = tegra_rt5640_dai.cpus->of_node; + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; From 1dd2e91b08d52eced666e1c1343960ac6374c6a7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:53 +0900 Subject: [PATCH 568/626] ASoC: tegra: tegra_rt5677: consider CPU-Platform possibility commit d035d13b2277 ("ASoC: tegra: tegra_rt5677: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit d035d13b2277 ("ASoC: tegra: tegra_rt5677: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_rt5677.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c index 738bdf876b13..81cb6cc6236e 100644 --- a/sound/soc/tegra/tegra_rt5677.c +++ b/sound/soc/tegra/tegra_rt5677.c @@ -160,7 +160,8 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5677-aif1"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5677-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tegra_rt5677_dai = { .name = "RT5677", @@ -259,6 +260,7 @@ static int tegra_rt5677_probe(struct platform_device *pdev) ret = -EINVAL; goto err_put_codec_of_node; } + tegra_rt5677_dai.platforms->of_node = tegra_rt5677_dai.cpus->of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) @@ -278,6 +280,7 @@ err_fini_utils: err_put_cpu_of_node: of_node_put(tegra_rt5677_dai.cpus->of_node); tegra_rt5677_dai.cpus->of_node = NULL; + tegra_rt5677_dai.platforms->of_node = NULL; err_put_codec_of_node: of_node_put(tegra_rt5677_dai.codecs->of_node); tegra_rt5677_dai.codecs->of_node = NULL; @@ -294,6 +297,7 @@ static int tegra_rt5677_remove(struct platform_device *pdev) tegra_asoc_utils_fini(&machine->util_data); + tegra_rt5677_dai.platforms->of_node = NULL; of_node_put(tegra_rt5677_dai.codecs->of_node); tegra_rt5677_dai.codecs->of_node = NULL; of_node_put(tegra_rt5677_dai.cpus->of_node); From be2428f3219c4eb32655a3e0db3f28d46e9d7986 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:48:58 +0900 Subject: [PATCH 569/626] ASoC: tegra: tegra_sgtl5000: consider CPU-Platform possibility commit cee1cf3f9f9e ("ASoC: tegra: tegra_sgtl5000: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit cee1cf3f9f9e ("ASoC: tegra: tegra_sgtl5000: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_sgtl5000.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c index 07504a2a7afc..e13b81d29cf3 100644 --- a/sound/soc/tegra/tegra_sgtl5000.c +++ b/sound/soc/tegra/tegra_sgtl5000.c @@ -83,7 +83,8 @@ static const struct snd_soc_dapm_widget tegra_sgtl5000_dapm_widgets[] = { SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tegra_sgtl5000_dai = { .name = "sgtl5000", @@ -145,6 +146,8 @@ static int tegra_sgtl5000_driver_probe(struct platform_device *pdev) goto err_put_codec_of_node; } + tegra_sgtl5000_dai.platforms->of_node = tegra_sgtl5000_dai.cpus->of_node; + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err_put_cpu_of_node; @@ -163,6 +166,7 @@ err_fini_utils: err_put_cpu_of_node: of_node_put(tegra_sgtl5000_dai.cpus->of_node); tegra_sgtl5000_dai.cpus->of_node = NULL; + tegra_sgtl5000_dai.platforms->of_node = NULL; err_put_codec_of_node: of_node_put(tegra_sgtl5000_dai.codecs->of_node); tegra_sgtl5000_dai.codecs->of_node = NULL; @@ -182,6 +186,7 @@ static int tegra_sgtl5000_driver_remove(struct platform_device *pdev) of_node_put(tegra_sgtl5000_dai.cpus->of_node); tegra_sgtl5000_dai.cpus->of_node = NULL; + tegra_sgtl5000_dai.platforms->of_node = NULL; of_node_put(tegra_sgtl5000_dai.codecs->of_node); tegra_sgtl5000_dai.codecs->of_node = NULL; From 9e4e02eae46cad3430b8f4c0a7a96a366c562e21 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:02 +0900 Subject: [PATCH 570/626] ASoC: tegra: tegra_wm8753: consider CPU-Platform possibility commit 404b229b84af ("ASoC: tegra: tegra_wm8753: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 404b229b84af ("ASoC: tegra: tegra_wm8753: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8753.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index fcb07c601ceb..f6dd790dad71 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -86,7 +86,8 @@ static const struct snd_soc_dapm_widget tegra_wm8753_dapm_widgets[] = { SND_SOC_DAILINK_DEFS(pcm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8753-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8753-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tegra_wm8753_dai = { .name = "WM8753", @@ -150,6 +151,8 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev) goto err; } + tegra_wm8753_dai.platforms->of_node = tegra_wm8753_dai.cpus->of_node; + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; From e8efc3ff9f839e4d3275a491554b24f17d14aa53 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:06 +0900 Subject: [PATCH 571/626] ASoC: tegra: tegra_wm8903: consider CPU-Platform possibility commit b28d98527157 ("ASoC: tegra: tegra_wm8903: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit b28d98527157 ("ASoC: tegra: tegra_wm8903: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index e512e50dc534..6211dfda2195 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -197,7 +197,8 @@ static int tegra_wm8903_remove(struct snd_soc_card *card) SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8903-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8903-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tegra_wm8903_dai = { .name = "WM8903", @@ -324,6 +325,8 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev) goto err; } + tegra_wm8903_dai.platforms->of_node = tegra_wm8903_dai.cpus->of_node; + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; From e0aad4b74fba62893a28ce860a99531d05e1d5ef Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:10 +0900 Subject: [PATCH 572/626] ASoC: tegra: tegra_wm9712: consider CPU-Platform possibility commit 5d62677238e9 ("ASoC: tegra: tegra_wm9712: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 5d62677238e9 ("ASoC: tegra: tegra_wm9712: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm9712.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c index b5faf709cc84..b85bd9f89073 100644 --- a/sound/soc/tegra/tegra_wm9712.c +++ b/sound/soc/tegra/tegra_wm9712.c @@ -42,7 +42,8 @@ static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link tegra_wm9712_dai = { .name = "AC97 HiFi", @@ -104,6 +105,8 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev) goto codec_unregister; } + tegra_wm9712_dai.platforms->of_node = tegra_wm9712_dai.cpus->of_node; + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto codec_unregister; From db1572d43ffbbe2d161d3e7a8fd5295667e42107 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:14 +0900 Subject: [PATCH 573/626] ASoC: tegra: trimslice: consider CPU-Platform possibility commit 567b374d9973 ("ASoC: tegra: trimslice: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 567b374d9973 ("ASoC: tegra: trimslice: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/tegra/trimslice.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 61e04a42eda3..3f67ddd13674 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -79,7 +79,8 @@ static const struct snd_soc_dapm_route trimslice_audio_map[] = { SND_SOC_DAILINK_DEFS(single_dsp, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { .name = "TLV320AIC23", @@ -137,6 +138,9 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev) goto err; } + trimslice_tlv320aic23_dai.platforms->of_node = + trimslice_tlv320aic23_dai.cpus->of_node; + ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); if (ret) goto err; From 44e578150f48e9e2517b41cdcababde0b0d0bfa4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:18 +0900 Subject: [PATCH 574/626] ASoC: ti: davinci-evm: consider CPU-Platform possibility commit f46da1b9046e ("ASoC: ti: davinci-evm: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit f46da1b9046e ("ASoC: ti: davinci-evm: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/davinci-evm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c index 6bac902bacf1..bfd8d1a03ba7 100644 --- a/sound/soc/ti/davinci-evm.c +++ b/sound/soc/ti/davinci-evm.c @@ -353,7 +353,8 @@ static struct snd_soc_card da850_snd_soc_card = { */ SND_SOC_DAILINK_DEFS(evm, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic3x-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link evm_dai_tlv320aic3x = { .name = "TLV320AIC3X", @@ -407,6 +408,8 @@ static int davinci_evm_probe(struct platform_device *pdev) if (!dai->cpus->of_node) return -EINVAL; + dai->platforms->of_node = dai->cpus->of_node; + evm_soc_card.dev = &pdev->dev; ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model"); if (ret) From b407a17a14475eea74e66ae6b531390ac0ea011c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:22 +0900 Subject: [PATCH 575/626] ASoC: ti: omap-abe-twl6040: consider CPU-Platform possibility commit 1306ab2eddd1 ("ASoC: ti: omap-abe-twl6040: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 1306ab2eddd1 ("ASoC: ti: omap-abe-twl6040: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-abe-twl6040.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c index 5572f5a8de9f..6d564ab5e437 100644 --- a/sound/soc/ti/omap-abe-twl6040.c +++ b/sound/soc/ti/omap-abe-twl6040.c @@ -21,17 +21,17 @@ #include "omap-mcpdm.h" #include "../codecs/twl6040.h" -SND_SOC_DAILINK_DEF(link0_cpus, - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEF(link0_codecs, +SND_SOC_DAILINK_DEFS(link0, + DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_CODEC("twl6040-codec", - "twl6040-legacy"))); - -SND_SOC_DAILINK_DEF(link1_cpus, + "twl6040-legacy")), DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEF(link1_codecs, + +SND_SOC_DAILINK_DEFS(link1, + DAILINK_COMP_ARRAY(COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", - "dmic-hifi"))); + "dmic-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); struct abe_twl6040 { struct snd_soc_card card; @@ -256,6 +256,9 @@ static int omap_abe_probe(struct platform_device *pdev) priv->dai_links[0].cpus = link0_cpus; priv->dai_links[0].num_cpus = 1; priv->dai_links[0].cpus->of_node = dai_node; + priv->dai_links[0].platforms = link0_platforms; + priv->dai_links[0].num_platforms = 1; + priv->dai_links[0].platforms->of_node = dai_node; priv->dai_links[0].codecs = link0_codecs; priv->dai_links[0].num_codecs = 1; priv->dai_links[0].init = omap_abe_twl6040_init; @@ -269,6 +272,9 @@ static int omap_abe_probe(struct platform_device *pdev) priv->dai_links[1].cpus = link1_cpus; priv->dai_links[1].num_cpus = 1; priv->dai_links[1].cpus->of_node = dai_node; + priv->dai_links[1].platforms = link1_platforms; + priv->dai_links[1].num_platforms = 1; + priv->dai_links[1].platforms->of_node = dai_node; priv->dai_links[1].codecs = link1_codecs; priv->dai_links[1].num_codecs = 1; priv->dai_links[1].init = omap_abe_dmic_init; From c5e8c53630a677a347a04e56df2e8c9f43f65c2e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:26 +0900 Subject: [PATCH 576/626] ASoC: ti: omap-hdmi: consider CPU-Platform possibility commit edba13aeae88 ("ASoC: ti: omap-hdmi: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit edba13aeae88 ("ASoC: ti: omap-hdmi: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-hdmi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index 0671f06c4699..def2a0ce8886 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -364,17 +364,20 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) if (!card->dai_link) return -ENOMEM; - compnent = devm_kzalloc(dev, 2 * sizeof(*compnent), GFP_KERNEL); + compnent = devm_kzalloc(dev, 3 * sizeof(*compnent), GFP_KERNEL); if (!compnent) return -ENOMEM; card->dai_link->cpus = &compnent[0]; card->dai_link->num_cpus = 1; card->dai_link->codecs = &compnent[1]; card->dai_link->num_codecs = 1; + card->dai_link->platforms = &compnent[2]; + card->dai_link->num_platforms = 1; card->dai_link->name = card->name; card->dai_link->stream_name = card->name; card->dai_link->cpus->dai_name = dev_name(ad->dssdev); + card->dai_link->platforms->name = dev_name(ad->dssdev); card->dai_link->codecs->name = "snd-soc-dummy"; card->dai_link->codecs->dai_name = "snd-soc-dummy-dai"; card->num_links = 1; From eb313e23da8da79cf18dff5ee1dbba3580df83b5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:30 +0900 Subject: [PATCH 577/626] ASoC: ti: omap-twl4030: consider CPU-Platform possibility commit bfe1273c65e1 ("ASoC: ti: omap-twl4030: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit bfe1273c65e1 ("ASoC: ti: omap-twl4030: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/omap-twl4030.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/soc/ti/omap-twl4030.c b/sound/soc/ti/omap-twl4030.c index 34e79e57f039..92dbe2c67290 100644 --- a/sound/soc/ti/omap-twl4030.c +++ b/sound/soc/ti/omap-twl4030.c @@ -197,11 +197,13 @@ static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) /* Digital audio interface glue - connects codec <--> CPU */ SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.2")), - DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.2"))); SND_SOC_DAILINK_DEFS(voice, DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.3")), - DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-voice"))); + DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec", "twl4030-voice")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.3"))); static struct snd_soc_dai_link omap_twl4030_dai_links[] = { { @@ -263,12 +265,18 @@ static int omap_twl4030_probe(struct platform_device *pdev) omap_twl4030_dai_links[0].cpus->dai_name = NULL; omap_twl4030_dai_links[0].cpus->of_node = dai_node; + omap_twl4030_dai_links[0].platforms->name = NULL; + omap_twl4030_dai_links[0].platforms->of_node = dai_node; + dai_node = of_parse_phandle(node, "ti,mcbsp-voice", 0); if (!dai_node) { card->num_links = 1; } else { omap_twl4030_dai_links[1].cpus->dai_name = NULL; omap_twl4030_dai_links[1].cpus->of_node = dai_node; + + omap_twl4030_dai_links[1].platforms->name = NULL; + omap_twl4030_dai_links[1].platforms->of_node = dai_node; } priv->jack_detect = of_get_named_gpio(node, From 569440b46baab1f9f696a688de7860a915cebc26 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:34 +0900 Subject: [PATCH 578/626] ASoC: ti: rx51: consider CPU-Platform possibility commit f0edc6c1ee48 ("ASoC: ti: rx51: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit f0edc6c1ee48 ("ASoC: ti: rx51: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ti/rx51.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index 4270cfb66224..bc6046534fa5 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -301,7 +301,8 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAILINK_DEFS(aic34, DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.2")), DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.2-0018", - "tlv320aic3x-hifi"))); + "tlv320aic3x-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.2"))); static struct snd_soc_dai_link rx51_dai[] = { { @@ -378,7 +379,9 @@ static int rx51_soc_probe(struct platform_device *pdev) return -EINVAL; } rx51_dai[0].cpus->dai_name = NULL; + rx51_dai[0].platforms->name = NULL; rx51_dai[0].cpus->of_node = dai_node; + rx51_dai[0].platforms->of_node = dai_node; dai_node = of_parse_phandle(np, "nokia,audio-codec", 0); if (!dai_node) { From 0296de83a6ca002c6ded44baed914ffdb66f709c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:40 +0900 Subject: [PATCH 579/626] ASoC: ux500: mop500: consider CPU-Platform possibility commit 9ae6cdb184b6 ("ASoC: ux500: mop500: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 9ae6cdb184b6 ("ASoC: ux500: mop500: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/ux500/mop500.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 6f66d395e24e..2873e8e6f02b 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -26,11 +26,13 @@ /* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ SND_SOC_DAILINK_DEFS(link1, DAILINK_COMP_ARRAY(COMP_CPU("ux500-msp-i2s.1")), - DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.0"))); + DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.0")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("ux500-msp-i2s.1"))); SND_SOC_DAILINK_DEFS(link2, DAILINK_COMP_ARRAY(COMP_CPU("ux500-msp-i2s.3")), - DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.1"))); + DAILINK_COMP_ARRAY(COMP_CODEC("ab8500-codec.0", "ab8500-codec-dai.1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("ux500-msp-i2s.3"))); static struct snd_soc_dai_link mop500_dai_links[] = { { @@ -86,6 +88,8 @@ static int mop500_of_probe(struct platform_device *pdev, for (i = 0; i < 2; i++) { mop500_dai_links[i].cpus->of_node = msp_np[i]; mop500_dai_links[i].cpus->dai_name = NULL; + mop500_dai_links[i].platforms->of_node = msp_np[i]; + mop500_dai_links[i].platforms->name = NULL; mop500_dai_links[i].codecs->of_node = codec_np; mop500_dai_links[i].codecs->name = NULL; } From 9f3eb917534511f2e275b7cf63ed76374ade77bc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:44 +0900 Subject: [PATCH 580/626] ASoC: simple-card-utils: consider CPU-Platform possibility commit 6f0437445735 ("ASoC: simple-card-utils: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 6f0437445735 ("ASoC: simple-card-utils: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 3cf5cb21ea52..ac8678fe55ff 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -346,18 +346,9 @@ EXPORT_SYMBOL_GPL(asoc_simple_dai_init); void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link) { - /* - * no Platform - * - * It will be waste of memory, but not be memory leak. - * see - * asoc_simple_init_priv() - * asoc_simple_priv - */ - if (!dai_link->platforms->of_node) { - dai_link->platforms = NULL; - dai_link->num_platforms = 0; - } + /* Assumes platform == cpu */ + if (!dai_link->platforms->of_node) + dai_link->platforms->of_node = dai_link->cpus->of_node; } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); From 0751154fda401d76d7ff025a9ca63678bf4ca021 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:48 +0900 Subject: [PATCH 581/626] ASoC: qcom: consider CPU-Platform possibility commit 0814c6412967 ("ASoC: qcom: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 0814c6412967 ("ASoC: qcom: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/qcom/common.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index adf49b198754..97488b5cc515 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -103,9 +103,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) link->codecs = dlc; link->num_codecs = 1; - link->platforms = NULL; - link->num_platforms = 0; - + link->platforms->of_node = link->cpus->of_node; link->codecs->dai_name = "snd-soc-dummy-dai"; link->codecs->name = "snd-soc-dummy"; link->dynamic = 1; From 6c10da54f3714afe26a2a205d0713d4841762d12 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:49:52 +0900 Subject: [PATCH 582/626] ASoC: rockchip: rk3399_gru_sound: consider CPU-Platform possibility commit 961fb3c206dc ("ASoC: rockchip: rk3399_gru_sound: don't select unnecessary Platform") Current ALSA SoC avoid to add duplicate component to rtd, and this driver was selecting CPU component as Platform component. Thus, above patch removed Platform settings from this driver, because it assumed these are same component. But, some CPU driver is using generic DMAEngine, in such case, both CPU component and Platform component will have same of_node/name. In other words, there are some components which are different but have same of_node/name. In such case, Card driver definitely need to select Platform even though it is same as CPU. It is depends on CPU driver, but is difficult to know it from Card driver. This patch reverts above patch. Fixes: commit 961fb3c206dc ("ASoC: rockchip: rk3399_gru_sound: don't select unnecessary Platform") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3399_gru_sound.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 46b6d1443f53..7a3e138594c1 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -255,27 +255,33 @@ enum { SND_SOC_DAILINK_DEFS(cdndp, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(da7219, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(dmic, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(max98357a, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(rt5514, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1"))); + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(rt5514_dsp, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_DUMMY())); + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); static const struct snd_soc_dai_link rockchip_dais[] = { [DAILINK_CDNDP] = { @@ -509,6 +515,7 @@ static int rockchip_sound_of_parse_dais(struct device *dev, if (!dai->codecs->name) dai->codecs->of_node = np_codec; + dai->platforms->of_node = np_cpu; dai->cpus->of_node = np_cpu; if (card->num_dapm_routes + rockchip_routes[index].num_routes > From aff50895269f567d1b30c688ce8d610542991b30 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 10:50:04 +0900 Subject: [PATCH 583/626] ASoC: soc-utils: respawn dummy Platform commit 64ee5067cf64 ("ASoC: soc-utils: remove dummy Platform") removed dummy Platform from ALSA SoC, but it is over-kill. This patch respawn it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-utils.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index f67e715a9f42..e3b9dd634c6d 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -262,6 +262,26 @@ static const struct snd_pcm_hardware dummy_dma_hardware = { .periods_max = 128, }; +static int dummy_dma_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + /* BE's dont need dummy params */ + if (!rtd->dai_link->no_pcm) + snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware); + + return 0; +} + +static const struct snd_pcm_ops snd_dummy_dma_ops = { + .open = dummy_dma_open, + .ioctl = snd_pcm_lib_ioctl, +}; + +static const struct snd_soc_component_driver dummy_platform = { + .ops = &snd_dummy_dma_ops, +}; + static const struct snd_soc_component_driver dummy_codec = { .idle_bias_on = 1, .use_pmdown_time = 1, @@ -319,6 +339,11 @@ static int snd_soc_dummy_probe(struct platform_device *pdev) ret = devm_snd_soc_register_component(&pdev->dev, &dummy_codec, &dummy_dai, 1); + if (ret < 0) + return ret; + + ret = devm_snd_soc_register_component(&pdev->dev, &dummy_platform, + NULL, 0); return ret; } From 2b9def8c0d92769eef3ef70d0a7c3646ab185d39 Mon Sep 17 00:00:00 2001 From: Derek Fang Date: Fri, 28 Jun 2019 20:51:43 +0800 Subject: [PATCH 584/626] ASoC: rt1308: Add RT1308 amplifier driver This is the initial amplifier driver for rt1308. Signed-off-by: Derek Fang Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/rt1308.txt | 17 + sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt1308.c | 899 ++++++++++++++++++ sound/soc/codecs/rt1308.h | 291 ++++++ 5 files changed, 1215 insertions(+) create mode 100755 Documentation/devicetree/bindings/sound/rt1308.txt create mode 100755 sound/soc/codecs/rt1308.c create mode 100755 sound/soc/codecs/rt1308.h diff --git a/Documentation/devicetree/bindings/sound/rt1308.txt b/Documentation/devicetree/bindings/sound/rt1308.txt new file mode 100755 index 000000000000..2d46084afce4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt1308.txt @@ -0,0 +1,17 @@ +RT1308 audio Amplifier + +This device supports I2C only. + +Required properties: + +- compatible : "realtek,rt1308". + +- reg : The I2C address of the device. + + +Example: + +rt1308: rt1308@10 { + compatible = "realtek,rt1308"; + reg = <0x10>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index b2d445b4bbf5..9f89a5346299 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -146,6 +146,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT298 if I2C select SND_SOC_RT1011 if I2C select SND_SOC_RT1305 if I2C + select SND_SOC_RT1308 if I2C select SND_SOC_RT5514 if I2C select SND_SOC_RT5616 if I2C select SND_SOC_RT5631 if I2C @@ -904,6 +905,7 @@ config SND_SOC_RL6231 default y if SND_SOC_RT5682=y default y if SND_SOC_RT1011=y default y if SND_SOC_RT1305=y + default y if SND_SOC_RT1308=y default m if SND_SOC_RT5514=m default m if SND_SOC_RT5616=m default m if SND_SOC_RT5640=m @@ -919,6 +921,7 @@ config SND_SOC_RL6231 default m if SND_SOC_RT5682=m default m if SND_SOC_RT1011=m default m if SND_SOC_RT1305=m + default m if SND_SOC_RT1308=m config SND_SOC_RL6347A tristate @@ -947,6 +950,9 @@ config SND_SOC_RT1011 config SND_SOC_RT1305 tristate +config SND_SOC_RT1308 + tristate + config SND_SOC_RT5514 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index ed74f5babf59..5b4bb8cf4325 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -148,6 +148,7 @@ snd-soc-rl6231-objs := rl6231.o snd-soc-rl6347a-objs := rl6347a.o snd-soc-rt1011-objs := rt1011.o snd-soc-rt1305-objs := rt1305.o +snd-soc-rt1308-objs := rt1308.o snd-soc-rt274-objs := rt274.o snd-soc-rt286-objs := rt286.o snd-soc-rt298-objs := rt298.o @@ -428,6 +429,7 @@ obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o +obj-$(CONFIG_SND_SOC_RT1308) += snd-soc-rt1308.o obj-$(CONFIG_SND_SOC_RT274) += snd-soc-rt274.o obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c new file mode 100755 index 000000000000..619a630e982e --- /dev/null +++ b/sound/soc/codecs/rt1308.c @@ -0,0 +1,899 @@ +/* + * rt1308.c -- RT1308 ALSA SoC amplifier component driver + * + * Copyright 2019 Realtek Semiconductor Corp. + * Author: Derek Fang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rl6231.h" +#include "rt1308.h" + +static const struct reg_sequence init_list[] = { + + { RT1308_I2C_I2S_SDW_SET, 0x01014005 }, + { RT1308_CLASS_D_SET_2, 0x227f5501 }, + { RT1308_PADS_1, 0x50150505 }, + { RT1308_VREF, 0x18100000 }, + { RT1308_IV_SENSE, 0x87010000 }, + { RT1308_DUMMY_REG, 0x00000200 }, + { RT1308_SIL_DET, 0x61c30000 }, + { RT1308_DC_CAL_2, 0x00ffff00 }, + { RT1308_CLK_DET, 0x01000000 }, + { RT1308_POWER_STATUS, 0x00800000 }, + { RT1308_DAC_SET, 0xafaf0700 }, + +}; +#define RT1308_INIT_REG_LEN ARRAY_SIZE(init_list) + +struct rt1308_priv { + struct snd_soc_component *component; + struct regmap *regmap; + + int sysclk; + int sysclk_src; + int lrck; + int bclk; + int master; + + int pll_src; + int pll_in; + int pll_out; +}; + +static const struct reg_default rt1308_reg[] = { + + { 0x01, 0x1f3f5f00 }, + { 0x02, 0x07000000 }, + { 0x03, 0x80003e00 }, + { 0x04, 0x80800600 }, + { 0x05, 0x0aaa1a0a }, + { 0x06, 0x52000000 }, + { 0x07, 0x00000000 }, + { 0x08, 0x00600000 }, + { 0x09, 0xe1030000 }, + { 0x0a, 0x00000000 }, + { 0x0b, 0x30000000 }, + { 0x0c, 0x7fff7000 }, + { 0x10, 0xffff0700 }, + { 0x11, 0x0a000000 }, + { 0x12, 0x60040000 }, + { 0x13, 0x00000000 }, + { 0x14, 0x0f300000 }, + { 0x15, 0x00000022 }, + { 0x16, 0x02000000 }, + { 0x17, 0x01004045 }, + { 0x18, 0x00000000 }, + { 0x19, 0x00000000 }, + { 0x1a, 0x80000000 }, + { 0x1b, 0x10325476 }, + { 0x1c, 0x1d1d0000 }, + { 0x20, 0xd2101300 }, + { 0x21, 0xf3ffff00 }, + { 0x22, 0x00000000 }, + { 0x23, 0x00000000 }, + { 0x24, 0x00000000 }, + { 0x25, 0x00000000 }, + { 0x26, 0x00000000 }, + { 0x27, 0x00000000 }, + { 0x28, 0x00000000 }, + { 0x29, 0x00000000 }, + { 0x2a, 0x00000000 }, + { 0x2b, 0x00000000 }, + { 0x2c, 0x00000000 }, + { 0x2d, 0x00000000 }, + { 0x2e, 0x00000000 }, + { 0x2f, 0x00000000 }, + { 0x30, 0x01000000 }, + { 0x31, 0x20025501 }, + { 0x32, 0x00000000 }, + { 0x33, 0x105a0000 }, + { 0x34, 0x10100000 }, + { 0x35, 0x2aaa52aa }, + { 0x36, 0x00c00000 }, + { 0x37, 0x20046100 }, + { 0x50, 0x10022f00 }, + { 0x51, 0x003c0000 }, + { 0x54, 0x04000000 }, + { 0x55, 0x01000000 }, + { 0x56, 0x02000000 }, + { 0x57, 0x02000000 }, + { 0x58, 0x02000000 }, + { 0x59, 0x02000000 }, + { 0x5b, 0x02000000 }, + { 0x5c, 0x00000000 }, + { 0x5d, 0x00000000 }, + { 0x5e, 0x00000000 }, + { 0x5f, 0x00000000 }, + { 0x60, 0x02000000 }, + { 0x61, 0x00000000 }, + { 0x62, 0x00000000 }, + { 0x63, 0x00000000 }, + { 0x64, 0x00000000 }, + { 0x65, 0x02000000 }, + { 0x66, 0x00000000 }, + { 0x67, 0x00000000 }, + { 0x68, 0x00000000 }, + { 0x69, 0x00000000 }, + { 0x6a, 0x02000000 }, + { 0x6c, 0x00000000 }, + { 0x6d, 0x00000000 }, + { 0x6e, 0x00000000 }, + { 0x70, 0x10EC1308 }, + { 0x71, 0x00000000 }, + { 0x72, 0x00000000 }, + { 0x73, 0x00000000 }, + { 0x74, 0x00000000 }, + { 0x75, 0x00000000 }, + { 0x76, 0x00000000 }, + { 0x77, 0x00000000 }, + { 0x78, 0x00000000 }, + { 0x79, 0x00000000 }, + { 0x7a, 0x00000000 }, + { 0x7b, 0x00000000 }, + { 0x7c, 0x00000000 }, + { 0x7d, 0x00000000 }, + { 0x7e, 0x00000000 }, + { 0x7f, 0x00020f00 }, + { 0x80, 0x00000000 }, + { 0x81, 0x00000000 }, + { 0x82, 0x00000000 }, + { 0x83, 0x00000000 }, + { 0x84, 0x00000000 }, + { 0x85, 0x00000000 }, + { 0x86, 0x00000000 }, + { 0x87, 0x00000000 }, + { 0x88, 0x00000000 }, + { 0x89, 0x00000000 }, + { 0x8a, 0x00000000 }, + { 0x8b, 0x00000000 }, + { 0x8c, 0x00000000 }, + { 0x8d, 0x00000000 }, + { 0x8e, 0x00000000 }, + { 0x90, 0x50250905 }, + { 0x91, 0x15050000 }, + { 0xa0, 0x00000000 }, + { 0xa1, 0x00000000 }, + { 0xa2, 0x00000000 }, + { 0xa3, 0x00000000 }, + { 0xa4, 0x00000000 }, + { 0xb0, 0x00000000 }, + { 0xb1, 0x00000000 }, + { 0xb2, 0x00000000 }, + { 0xb3, 0x00000000 }, + { 0xb4, 0x00000000 }, + { 0xb5, 0x00000000 }, + { 0xb6, 0x00000000 }, + { 0xb7, 0x00000000 }, + { 0xb8, 0x00000000 }, + { 0xb9, 0x00000000 }, + { 0xba, 0x00000000 }, + { 0xbb, 0x00000000 }, + { 0xc0, 0x01000000 }, + { 0xc1, 0x00000000 }, + { 0xf0, 0x00000000 }, +}; + +static int rt1308_reg_init(struct snd_soc_component *component) +{ + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + + return regmap_multi_reg_write(rt1308->regmap, init_list, + RT1308_INIT_REG_LEN); +} + +static bool rt1308_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT1308_RESET: + case RT1308_RESET_N: + case RT1308_CLK_2: + case RT1308_SIL_DET: + case RT1308_CLK_DET: + case RT1308_DC_DET: + case RT1308_DAC_SET: + case RT1308_DAC_BUF: + case RT1308_SDW_REG_RDATA: + case RT1308_DC_CAL_1: + case RT1308_PVDD_OFFSET_CTL: + case RT1308_CAL_OFFSET_DAC_PBTL: + case RT1308_CAL_OFFSET_DAC_L: + case RT1308_CAL_OFFSET_DAC_R: + case RT1308_CAL_OFFSET_PWM_L: + case RT1308_CAL_OFFSET_PWM_R: + case RT1308_CAL_PWM_VOS_ADC_L: + case RT1308_CAL_PWM_VOS_ADC_R: + case RT1308_MBIAS: + case RT1308_POWER_STATUS: + case RT1308_POWER_INT: + case RT1308_SINE_TONE_GEN_2: + case RT1308_BQ_SET: + case RT1308_BQ_PARA_UPDATE: + case RT1308_VEN_DEV_ID: + case RT1308_VERSION_ID: + case RT1308_EFUSE_1: + case RT1308_EFUSE_READ_PVDD_L: + case RT1308_EFUSE_READ_PVDD_R: + case RT1308_EFUSE_READ_PVDD_PTBL: + case RT1308_EFUSE_READ_DEV: + case RT1308_EFUSE_READ_R0: + case RT1308_EFUSE_READ_ADC_L: + case RT1308_EFUSE_READ_ADC_R: + case RT1308_EFUSE_READ_ADC_PBTL: + case RT1308_EFUSE_RESERVE: + case RT1308_EFUSE_DATA_0_MSB: + case RT1308_EFUSE_DATA_0_LSB: + case RT1308_EFUSE_DATA_1_MSB: + case RT1308_EFUSE_DATA_1_LSB: + case RT1308_EFUSE_DATA_2_MSB: + case RT1308_EFUSE_DATA_2_LSB: + case RT1308_EFUSE_DATA_3_MSB: + case RT1308_EFUSE_DATA_3_LSB: + case RT1308_EFUSE_STATUS_1: + case RT1308_EFUSE_STATUS_2: + case RT1308_DUMMY_REG: + return true; + default: + return false; + } +} + +static bool rt1308_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT1308_RESET: + case RT1308_RESET_N: + case RT1308_CLK_GATING ... RT1308_DC_DET_THRES: + case RT1308_DAC_SET ... RT1308_AD_FILTER_SET: + case RT1308_DC_CAL_1 ... RT1308_POWER_INT: + case RT1308_SINE_TONE_GEN_1: + case RT1308_SINE_TONE_GEN_2: + case RT1308_BQ_SET: + case RT1308_BQ_PARA_UPDATE: + case RT1308_BQ_PRE_VOL_L ... RT1308_BQ_POST_VOL_R: + case RT1308_BQ1_L_H0 ... RT1308_BQ2_R_A2: + case RT1308_VEN_DEV_ID: + case RT1308_VERSION_ID: + case RT1308_SPK_BOUND: + case RT1308_BQ1_EQ_L_1 ... RT1308_BQ2_EQ_R_3: + case RT1308_EFUSE_1 ... RT1308_EFUSE_RESERVE: + case RT1308_PADS_1: + case RT1308_PADS_2: + case RT1308_TEST_MODE: + case RT1308_TEST_1: + case RT1308_TEST_2: + case RT1308_TEST_3: + case RT1308_TEST_4: + case RT1308_EFUSE_DATA_0_MSB ... RT1308_EFUSE_STATUS_2: + case RT1308_TCON_1: + case RT1308_TCON_2: + case RT1308_DUMMY_REG: + case RT1308_MAX_REG: + return true; + default: + return false; + } +} + +static int rt1308_classd_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + msleep(30); + snd_soc_component_update_bits(component, RT1308_POWER_STATUS, + RT1308_POW_PDB_REG_BIT, RT1308_POW_PDB_REG_BIT); + msleep(40); + break; + case SND_SOC_DAPM_PRE_PMD: + snd_soc_component_update_bits(component, RT1308_POWER_STATUS, + RT1308_POW_PDB_REG_BIT, 0); + usleep_range(150000, 200000); + break; + + default: + break; + } + + return 0; +} + +static const char * const rt1308_rx_data_ch_select[] = { + "LR", + "LL", + "RL", + "RR", +}; + +static SOC_ENUM_SINGLE_DECL(rt1308_rx_data_ch_enum, RT1308_DATA_PATH, 24, + rt1308_rx_data_ch_select); + +static const struct snd_kcontrol_new rt1308_snd_controls[] = { + + /* I2S Data Channel Selection */ + SOC_ENUM("RX Channel Select", rt1308_rx_data_ch_enum), +}; + +static const struct snd_kcontrol_new rt1308_sto_dac_l = + SOC_DAPM_SINGLE("Switch", RT1308_DAC_SET, + RT1308_DVOL_MUTE_L_EN_SFT, 1, 1); + +static const struct snd_kcontrol_new rt1308_sto_dac_r = + SOC_DAPM_SINGLE("Switch", RT1308_DAC_SET, + RT1308_DVOL_MUTE_R_EN_SFT, 1, 1); + +static const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = { + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + + /* Supply Widgets */ + SND_SOC_DAPM_SUPPLY("MBIAS20U", RT1308_POWER, + RT1308_POW_MBIAS20U_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ALDO", RT1308_POWER, + RT1308_POW_ALDO_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DBG", RT1308_POWER, + RT1308_POW_DBG_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DACL", RT1308_POWER, + RT1308_POW_DACL_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CLK25M", RT1308_POWER, + RT1308_POW_CLK25M_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC_R", RT1308_POWER, + RT1308_POW_ADC_R_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC_L", RT1308_POWER, + RT1308_POW_ADC_L_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DLDO", RT1308_POWER, + RT1308_POW_DLDO_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("VREF", RT1308_POWER, + RT1308_POW_VREF_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MIXER_R", RT1308_POWER, + RT1308_POW_MIXER_R_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MIXER_L", RT1308_POWER, + RT1308_POW_MIXER_L_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MBIAS4U", RT1308_POWER, + RT1308_POW_MBIAS4U_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL2_LDO", RT1308_POWER, + RT1308_POW_PLL2_LDO_EN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL2B", RT1308_POWER, + RT1308_POW_PLL2B_EN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL2F", RT1308_POWER, + RT1308_POW_PLL2F_EN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL2F2", RT1308_POWER, + RT1308_POW_PLL2F2_EN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL2B2", RT1308_POWER, + RT1308_POW_PLL2B2_EN_BIT, 0, NULL, 0), + + /* Digital Interface */ + SND_SOC_DAPM_SUPPLY("DAC Power", RT1308_POWER, + RT1308_POW_DAC1_BIT, 0, NULL, 0), + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_SWITCH("DAC L", SND_SOC_NOPM, 0, 0, &rt1308_sto_dac_l), + SND_SOC_DAPM_SWITCH("DAC R", SND_SOC_NOPM, 0, 0, &rt1308_sto_dac_r), + + /* Output Lines */ + SND_SOC_DAPM_PGA_E("CLASS D", SND_SOC_NOPM, 0, 0, NULL, 0, + rt1308_classd_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_OUTPUT("SPOL"), + SND_SOC_DAPM_OUTPUT("SPOR"), +}; + +static const struct snd_soc_dapm_route rt1308_dapm_routes[] = { + + { "DAC", NULL, "AIF1RX" }, + + { "DAC", NULL, "MBIAS20U" }, + { "DAC", NULL, "ALDO" }, + { "DAC", NULL, "DBG" }, + { "DAC", NULL, "DACL" }, + { "DAC", NULL, "CLK25M" }, + { "DAC", NULL, "ADC_R" }, + { "DAC", NULL, "ADC_L" }, + { "DAC", NULL, "DLDO" }, + { "DAC", NULL, "VREF" }, + { "DAC", NULL, "MIXER_R" }, + { "DAC", NULL, "MIXER_L" }, + { "DAC", NULL, "MBIAS4U" }, + { "DAC", NULL, "PLL2_LDO" }, + { "DAC", NULL, "PLL2B" }, + { "DAC", NULL, "PLL2F" }, + { "DAC", NULL, "PLL2F2" }, + { "DAC", NULL, "PLL2B2" }, + + { "DAC L", "Switch", "DAC" }, + { "DAC R", "Switch", "DAC" }, + { "DAC L", NULL, "DAC Power" }, + { "DAC R", NULL, "DAC Power" }, + + { "CLASS D", NULL, "DAC L" }, + { "CLASS D", NULL, "DAC R" }, + { "SPOL", NULL, "CLASS D" }, + { "SPOR", NULL, "CLASS D" }, +}; + +static int rt1308_get_clk_info(int sclk, int rate) +{ + int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; + + if (sclk <= 0 || rate <= 0) + return -EINVAL; + + rate = rate << 8; + for (i = 0; i < ARRAY_SIZE(pd); i++) + if (sclk == rate * pd[i]) + return i; + + return -EINVAL; +} + +static int rt1308_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + unsigned int val_len = 0, val_clk, mask_clk; + int pre_div, bclk_ms, frame_size; + + rt1308->lrck = params_rate(params); + pre_div = rt1308_get_clk_info(rt1308->sysclk, rt1308->lrck); + if (pre_div < 0) { + dev_err(component->dev, + "Unsupported clock setting %d\n", rt1308->lrck); + return -EINVAL; + } + + frame_size = snd_soc_params_to_frame_size(params); + if (frame_size < 0) { + dev_err(component->dev, "Unsupported frame size: %d\n", + frame_size); + return -EINVAL; + } + + bclk_ms = frame_size > 32; + rt1308->bclk = rt1308->lrck * (32 << bclk_ms); + + dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", + bclk_ms, pre_div, dai->id); + + dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n", + rt1308->lrck, pre_div, dai->id); + + switch (params_width(params)) { + case 16: + val_len |= RT1308_I2S_DL_SEL_16B; + break; + case 20: + val_len |= RT1308_I2S_DL_SEL_20B; + break; + case 24: + val_len |= RT1308_I2S_DL_SEL_24B; + break; + case 8: + val_len |= RT1308_I2S_DL_SEL_8B; + break; + default: + return -EINVAL; + } + + switch (dai->id) { + case RT1308_AIF1: + mask_clk = RT1308_DIV_FS_SYS_MASK; + val_clk = pre_div << RT1308_DIV_FS_SYS_SFT; + snd_soc_component_update_bits(component, + RT1308_I2S_SET_2, RT1308_I2S_DL_SEL_MASK, + val_len); + break; + default: + dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + + snd_soc_component_update_bits(component, RT1308_CLK_1, + mask_clk, val_clk); + + return 0; +} + +static int rt1308_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + unsigned int reg_val = 0, reg1_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + rt1308->master = 0; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_LEFT_J: + reg_val |= RT1308_I2S_DF_SEL_LEFT; + break; + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT1308_I2S_DF_SEL_PCM_A; + break; + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT1308_I2S_DF_SEL_PCM_B; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + reg1_val |= RT1308_I2S_BCLK_INV; + break; + default: + return -EINVAL; + } + + switch (dai->id) { + case RT1308_AIF1: + snd_soc_component_update_bits(component, + RT1308_I2S_SET_1, RT1308_I2S_DF_SEL_MASK, + reg_val); + snd_soc_component_update_bits(component, + RT1308_I2S_SET_2, RT1308_I2S_BCLK_MASK, + reg1_val); + break; + default: + dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + return 0; +} + +static int rt1308_set_component_sysclk(struct snd_soc_component *component, + int clk_id, int source, unsigned int freq, int dir) +{ + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + unsigned int reg_val = 0; + + if (freq == rt1308->sysclk && clk_id == rt1308->sysclk_src) + return 0; + + switch (clk_id) { + case RT1308_FS_SYS_S_MCLK: + reg_val |= RT1308_SEL_FS_SYS_SRC_MCLK; + snd_soc_component_update_bits(component, + RT1308_CLK_DET, RT1308_MCLK_DET_EN_MASK, + RT1308_MCLK_DET_EN); + break; + case RT1308_FS_SYS_S_BCLK: + reg_val |= RT1308_SEL_FS_SYS_SRC_BCLK; + break; + case RT1308_FS_SYS_S_PLL: + reg_val |= RT1308_SEL_FS_SYS_SRC_PLL; + break; + case RT1308_FS_SYS_S_RCCLK: + reg_val |= RT1308_SEL_FS_SYS_SRC_RCCLK; + break; + default: + dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + snd_soc_component_update_bits(component, RT1308_CLK_1, + RT1308_SEL_FS_SYS_MASK, reg_val); + rt1308->sysclk = freq; + rt1308->sysclk_src = clk_id; + + dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n", + freq, clk_id); + + return 0; +} + +static int rt1308_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, unsigned int freq_in, + unsigned int freq_out) +{ + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + struct rl6231_pll_code pll_code; + int ret; + + if (source == rt1308->pll_src && freq_in == rt1308->pll_in && + freq_out == rt1308->pll_out) + return 0; + + if (!freq_in || !freq_out) { + dev_dbg(component->dev, "PLL disabled\n"); + + rt1308->pll_in = 0; + rt1308->pll_out = 0; + snd_soc_component_update_bits(component, + RT1308_CLK_1, RT1308_SEL_FS_SYS_MASK, + RT1308_SEL_FS_SYS_SRC_MCLK); + return 0; + } + + switch (source) { + case RT1308_PLL_S_MCLK: + snd_soc_component_update_bits(component, + RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK, + RT1308_SEL_PLL_SRC_MCLK); + snd_soc_component_update_bits(component, + RT1308_CLK_DET, RT1308_MCLK_DET_EN_MASK, + RT1308_MCLK_DET_EN); + break; + case RT1308_PLL_S_BCLK: + snd_soc_component_update_bits(component, + RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK, + RT1308_SEL_PLL_SRC_BCLK); + break; + case RT1308_PLL_S_RCCLK: + snd_soc_component_update_bits(component, + RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK, + RT1308_SEL_PLL_SRC_RCCLK); + freq_in = 25000000; + break; + default: + dev_err(component->dev, "Unknown PLL Source %d\n", source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(component->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), + pll_code.n_code, pll_code.k_code); + + snd_soc_component_write(component, RT1308_PLL_1, + pll_code.k_code << RT1308_PLL1_K_SFT | + pll_code.m_bp << RT1308_PLL1_M_BYPASS_SFT | + (pll_code.m_bp ? 0 : pll_code.m_code) << RT1308_PLL1_M_SFT | + pll_code.n_code << RT1308_PLL1_N_SFT); + + rt1308->pll_in = freq_in; + rt1308->pll_out = freq_out; + rt1308->pll_src = source; + + return 0; +} + +static int rt1308_probe(struct snd_soc_component *component) +{ + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + + rt1308->component = component; + + return rt1308_reg_init(component); +} + +static void rt1308_remove(struct snd_soc_component *component) +{ + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + + regmap_write(rt1308->regmap, RT1308_RESET, 0); +} + +#ifdef CONFIG_PM +static int rt1308_suspend(struct snd_soc_component *component) +{ + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt1308->regmap, true); + regcache_mark_dirty(rt1308->regmap); + + return 0; +} + +static int rt1308_resume(struct snd_soc_component *component) +{ + struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt1308->regmap, false); + regcache_sync(rt1308->regmap); + + return 0; +} +#else +#define rt1308_suspend NULL +#define rt1308_resume NULL +#endif + +#define RT1308_STEREO_RATES SNDRV_PCM_RATE_48000 +#define RT1308_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops rt1308_aif_dai_ops = { + .hw_params = rt1308_hw_params, + .set_fmt = rt1308_set_dai_fmt, +}; + +static struct snd_soc_dai_driver rt1308_dai[] = { + { + .name = "rt1308-aif", + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT1308_STEREO_RATES, + .formats = RT1308_FORMATS, + }, + .ops = &rt1308_aif_dai_ops, + }, +}; + +static const struct snd_soc_component_driver soc_component_dev_rt1308 = { + .probe = rt1308_probe, + .remove = rt1308_remove, + .suspend = rt1308_suspend, + .resume = rt1308_resume, + .controls = rt1308_snd_controls, + .num_controls = ARRAY_SIZE(rt1308_snd_controls), + .dapm_widgets = rt1308_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt1308_dapm_widgets), + .dapm_routes = rt1308_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt1308_dapm_routes), + .set_sysclk = rt1308_set_component_sysclk, + .set_pll = rt1308_set_component_pll, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct regmap_config rt1308_regmap = { + .reg_bits = 8, + .val_bits = 32, + .max_register = RT1308_MAX_REG, + .volatile_reg = rt1308_volatile_register, + .readable_reg = rt1308_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt1308_reg, + .num_reg_defaults = ARRAY_SIZE(rt1308_reg), + .use_single_read = true, + .use_single_write = true, +}; + +#ifdef CONFIG_OF +static const struct of_device_id rt1308_of_match[] = { + { .compatible = "realtek,rt1308", }, + { }, +}; +MODULE_DEVICE_TABLE(of, rt1308_of_match); +#endif + +#ifdef CONFIG_ACPI +static struct acpi_device_id rt1308_acpi_match[] = { + { "10EC1308", 0, }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, rt1308_acpi_match); +#endif + +static const struct i2c_device_id rt1308_i2c_id[] = { + { "rt1308", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt1308_i2c_id); + +static void rt1308_efuse(struct rt1308_priv *rt1308) +{ + regmap_write(rt1308->regmap, RT1308_RESET, 0); + + regmap_write(rt1308->regmap, RT1308_POWER, 0xff371600); + regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52100000); + regmap_write(rt1308->regmap, RT1308_I2C_I2S_SDW_SET, 0x01014005); + regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501); + regmap_write(rt1308->regmap, RT1308_PADS_1, 0x50150505); + regmap_write(rt1308->regmap, RT1308_VREF, 0x18100000); + regmap_write(rt1308->regmap, RT1308_IV_SENSE, 0x87010000); + regmap_write(rt1308->regmap, RT1308_DUMMY_REG, 0x00000200); + regmap_write(rt1308->regmap, RT1308_SIL_DET, 0x61c30000); + regmap_write(rt1308->regmap, RT1308_CLK_DET, 0x03700000); + regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x50022f00); + regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000); + regmap_write(rt1308->regmap, RT1308_DC_CAL_2, 0x00ffff00); + regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x607e5501); + + regmap_write(rt1308->regmap, RT1308_CLK_2, 0x0060e000); + regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x04fe0f00); + msleep(100); + regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00); + msleep(20); + regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000); + + regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x00800000); + regmap_write(rt1308->regmap, RT1308_POWER, 0x0); + regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52000000); + regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501); + regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x10022f00); +} + +static int rt1308_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt1308_priv *rt1308; + int ret; + unsigned int val; + + rt1308 = devm_kzalloc(&i2c->dev, sizeof(struct rt1308_priv), + GFP_KERNEL); + if (rt1308 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt1308); + + rt1308->regmap = devm_regmap_init_i2c(i2c, &rt1308_regmap); + if (IS_ERR(rt1308->regmap)) { + ret = PTR_ERR(rt1308->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + regmap_read(rt1308->regmap, RT1308_VEN_DEV_ID, &val); + /* ignore last byte difference */ + if ((val & 0xFFFFFF00) != RT1308_DEVICE_ID_NUM) { + dev_err(&i2c->dev, + "Device with ID register %x is not rt1308\n", val); + return -ENODEV; + } + + rt1308_efuse(rt1308); + + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_rt1308, + rt1308_dai, ARRAY_SIZE(rt1308_dai)); +} + +static void rt1308_i2c_shutdown(struct i2c_client *client) +{ + struct rt1308_priv *rt1308 = i2c_get_clientdata(client); + + regmap_write(rt1308->regmap, RT1308_RESET, 0); +} + +static struct i2c_driver rt1308_i2c_driver = { + .driver = { + .name = "rt1308", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rt1308_of_match), + .acpi_match_table = ACPI_PTR(rt1308_acpi_match), + }, + .probe = rt1308_i2c_probe, + .shutdown = rt1308_i2c_shutdown, + .id_table = rt1308_i2c_id, +}; +module_i2c_driver(rt1308_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT1308 amplifier driver"); +MODULE_AUTHOR("Derek Fang "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt1308.h b/sound/soc/codecs/rt1308.h new file mode 100755 index 000000000000..c330aae1d527 --- /dev/null +++ b/sound/soc/codecs/rt1308.h @@ -0,0 +1,291 @@ +/* + * RT1308.h -- RT1308 ALSA SoC amplifier component driver + * + * Copyright 2019 Realtek Semiconductor Corp. + * Author: Derek Fang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _RT1308_H_ +#define _RT1308_H_ + +#define RT1308_DEVICE_ID_NUM 0x10ec1300 + +#define RT1308_RESET 0x00 +#define RT1308_RESET_N 0x01 +#define RT1308_CLK_GATING 0x02 +#define RT1308_PLL_1 0x03 +#define RT1308_PLL_2 0x04 +#define RT1308_PLL_INT 0x05 +#define RT1308_CLK_1 0x06 +#define RT1308_DATA_PATH 0x07 +#define RT1308_CLK_2 0x08 +#define RT1308_SIL_DET 0x09 +#define RT1308_CLK_DET 0x0a +#define RT1308_DC_DET 0x0b +#define RT1308_DC_DET_THRES 0x0c +#define RT1308_DAC_SET 0x10 +#define RT1308_SRC_SET 0x11 +#define RT1308_DAC_BUF 0x12 +#define RT1308_ADC_SET 0x13 +#define RT1308_ADC_SET_INT 0x14 +#define RT1308_I2S_SET_1 0x15 +#define RT1308_I2S_SET_2 0x16 +#define RT1308_I2C_I2S_SDW_SET 0x17 +#define RT1308_SDW_REG_RW 0x18 +#define RT1308_SDW_REG_RDATA 0x19 +#define RT1308_IV_SENSE 0x1a +#define RT1308_I2S_TX_DAC_SET 0x1b +#define RT1308_AD_FILTER_SET 0x1c +#define RT1308_DC_CAL_1 0x20 +#define RT1308_DC_CAL_2 0x21 +#define RT1308_DC_CAL_L_OFFSET 0x22 +#define RT1308_DC_CAL_R_OFFSET 0x23 +#define RT1308_PVDD_OFFSET_CTL 0x24 +#define RT1308_PVDD_OFFSET_L 0x25 +#define RT1308_PVDD_OFFSET_R 0x26 +#define RT1308_PVDD_OFFSET_PBTL 0x27 +#define RT1308_PVDD_OFFSET_PVDD 0x28 +#define RT1308_CAL_OFFSET_DAC_PBTL 0x29 +#define RT1308_CAL_OFFSET_DAC_L 0x2a +#define RT1308_CAL_OFFSET_DAC_R 0x2b +#define RT1308_CAL_OFFSET_PWM_L 0x2c +#define RT1308_CAL_OFFSET_PWM_R 0x2d +#define RT1308_CAL_PWM_VOS_ADC_L 0x2e +#define RT1308_CAL_PWM_VOS_ADC_R 0x2f +#define RT1308_CLASS_D_SET_1 0x30 +#define RT1308_CLASS_D_SET_2 0x31 +#define RT1308_POWER 0x32 +#define RT1308_LDO 0x33 +#define RT1308_VREF 0x34 +#define RT1308_MBIAS 0x35 +#define RT1308_POWER_STATUS 0x36 +#define RT1308_POWER_INT 0x37 +#define RT1308_SINE_TONE_GEN_1 0x50 +#define RT1308_SINE_TONE_GEN_2 0x51 +#define RT1308_BQ_SET 0x54 +#define RT1308_BQ_PARA_UPDATE 0x55 +#define RT1308_BQ_PRE_VOL_L 0x56 +#define RT1308_BQ_PRE_VOL_R 0x57 +#define RT1308_BQ_POST_VOL_L 0x58 +#define RT1308_BQ_POST_VOL_R 0x59 +#define RT1308_BQ1_L_H0 0x5b +#define RT1308_BQ1_L_B1 0x5c +#define RT1308_BQ1_L_B2 0x5d +#define RT1308_BQ1_L_A1 0x5e +#define RT1308_BQ1_L_A2 0x5f +#define RT1308_BQ1_R_H0 0x60 +#define RT1308_BQ1_R_B1 0x61 +#define RT1308_BQ1_R_B2 0x62 +#define RT1308_BQ1_R_A1 0x63 +#define RT1308_BQ1_R_A2 0x64 +#define RT1308_BQ2_L_H0 0x65 +#define RT1308_BQ2_L_B1 0x66 +#define RT1308_BQ2_L_B2 0x67 +#define RT1308_BQ2_L_A1 0x68 +#define RT1308_BQ2_L_A2 0x69 +#define RT1308_BQ2_R_H0 0x6a +#define RT1308_BQ2_R_B1 0x6b +#define RT1308_BQ2_R_B2 0x6c +#define RT1308_BQ2_R_A1 0x6d +#define RT1308_BQ2_R_A2 0x6e +#define RT1308_VEN_DEV_ID 0x70 +#define RT1308_VERSION_ID 0x71 +#define RT1308_SPK_BOUND 0x72 +#define RT1308_BQ1_EQ_L_1 0x73 +#define RT1308_BQ1_EQ_L_2 0x74 +#define RT1308_BQ1_EQ_L_3 0x75 +#define RT1308_BQ1_EQ_R_1 0x76 +#define RT1308_BQ1_EQ_R_2 0x77 +#define RT1308_BQ1_EQ_R_3 0x78 +#define RT1308_BQ2_EQ_L_1 0x79 +#define RT1308_BQ2_EQ_L_2 0x7a +#define RT1308_BQ2_EQ_L_3 0x7b +#define RT1308_BQ2_EQ_R_1 0x7c +#define RT1308_BQ2_EQ_R_2 0x7d +#define RT1308_BQ2_EQ_R_3 0x7e +#define RT1308_EFUSE_1 0x7f +#define RT1308_EFUSE_2 0x80 +#define RT1308_EFUSE_PROG_PVDD_L 0x81 +#define RT1308_EFUSE_PROG_PVDD_R 0x82 +#define RT1308_EFUSE_PROG_R0_L 0x83 +#define RT1308_EFUSE_PROG_R0_R 0x84 +#define RT1308_EFUSE_PROG_DEV 0x85 +#define RT1308_EFUSE_READ_PVDD_L 0x86 +#define RT1308_EFUSE_READ_PVDD_R 0x87 +#define RT1308_EFUSE_READ_PVDD_PTBL 0x88 +#define RT1308_EFUSE_READ_DEV 0x89 +#define RT1308_EFUSE_READ_R0 0x8a +#define RT1308_EFUSE_READ_ADC_L 0x8b +#define RT1308_EFUSE_READ_ADC_R 0x8c +#define RT1308_EFUSE_READ_ADC_PBTL 0x8d +#define RT1308_EFUSE_RESERVE 0x8e +#define RT1308_PADS_1 0x90 +#define RT1308_PADS_2 0x91 +#define RT1308_TEST_MODE 0xa0 +#define RT1308_TEST_1 0xa1 +#define RT1308_TEST_2 0xa2 +#define RT1308_TEST_3 0xa3 +#define RT1308_TEST_4 0xa4 +#define RT1308_EFUSE_DATA_0_MSB 0xb0 +#define RT1308_EFUSE_DATA_0_LSB 0xb1 +#define RT1308_EFUSE_DATA_1_MSB 0xb2 +#define RT1308_EFUSE_DATA_1_LSB 0xb3 +#define RT1308_EFUSE_DATA_2_MSB 0xb4 +#define RT1308_EFUSE_DATA_2_LSB 0xb5 +#define RT1308_EFUSE_DATA_3_MSB 0xb6 +#define RT1308_EFUSE_DATA_3_LSB 0xb7 +#define RT1308_EFUSE_DATA_TEST_MSB 0xb8 +#define RT1308_EFUSE_DATA_TEST_LSB 0xb9 +#define RT1308_EFUSE_STATUS_1 0xba +#define RT1308_EFUSE_STATUS_2 0xbb +#define RT1308_TCON_1 0xc0 +#define RT1308_TCON_2 0xc1 +#define RT1308_DUMMY_REG 0xf0 +#define RT1308_MAX_REG 0xff + +/* PLL1 M/N/K Code-1 (0x03) */ +#define RT1308_PLL1_K_SFT 24 +#define RT1308_PLL1_K_MASK (0x1f << 24) +#define RT1308_PLL1_M_BYPASS_MASK (0x1 << 23) +#define RT1308_PLL1_M_BYPASS_SFT 23 +#define RT1308_PLL1_M_BYPASS (0x1 << 23) +#define RT1308_PLL1_M_MASK (0x3f << 16) +#define RT1308_PLL1_M_SFT 16 +#define RT1308_PLL1_N_MASK (0x7f << 8) +#define RT1308_PLL1_N_SFT 8 + +/* CLOCK-1 (0x06) */ +#define RT1308_DIV_FS_SYS_MASK (0xf << 28) +#define RT1308_DIV_FS_SYS_SFT 28 +#define RT1308_SEL_FS_SYS_MASK (0x7 << 24) +#define RT1308_SEL_FS_SYS_SFT 24 +#define RT1308_SEL_FS_SYS_SRC_MCLK (0x0 << 24) +#define RT1308_SEL_FS_SYS_SRC_BCLK (0x1 << 24) +#define RT1308_SEL_FS_SYS_SRC_PLL (0x2 << 24) +#define RT1308_SEL_FS_SYS_SRC_RCCLK (0x4 << 24) + +/* CLOCK-2 (0x08) */ +#define RT1308_DIV_PRE_PLL_MASK (0xf << 28) +#define RT1308_DIV_PRE_PLL_SFT 28 +#define RT1308_SEL_PLL_SRC_MASK (0x7 << 24) +#define RT1308_SEL_PLL_SRC_SFT 24 +#define RT1308_SEL_PLL_SRC_MCLK (0x0 << 24) +#define RT1308_SEL_PLL_SRC_BCLK (0x1 << 24) +#define RT1308_SEL_PLL_SRC_RCCLK (0x4 << 24) + +/* Clock Detect (0x0a) */ +#define RT1308_MCLK_DET_EN_MASK (0x1 << 25) +#define RT1308_MCLK_DET_EN_SFT 25 +#define RT1308_MCLK_DET_EN (0x1 << 25) +#define RT1308_BCLK_DET_EN_MASK (0x1 << 24) +#define RT1308_BCLK_DET_EN_SFT 24 +#define RT1308_BCLK_DET_EN (0x1 << 24) + +/* DAC Setting (0x10) */ +#define RT1308_DVOL_MUTE_R_EN_SFT 7 +#define RT1308_DVOL_MUTE_L_EN_SFT 6 + +/* I2S Setting-1 (0x15) */ +#define RT1308_I2S_DF_SEL_MASK (0x3 << 12) +#define RT1308_I2S_DF_SEL_SFT 12 +#define RT1308_I2S_DF_SEL_I2S (0x0 << 12) +#define RT1308_I2S_DF_SEL_LEFT (0x1 << 12) +#define RT1308_I2S_DF_SEL_PCM_A (0x2 << 12) +#define RT1308_I2S_DF_SEL_PCM_B (0x3 << 12) +#define RT1308_I2S_DL_RX_SEL_MASK (0x7 << 4) +#define RT1308_I2S_DL_RX_SEL_SFT 4 +#define RT1308_I2S_DL_RX_SEL_16B (0x0 << 4) +#define RT1308_I2S_DL_RX_SEL_20B (0x1 << 4) +#define RT1308_I2S_DL_RX_SEL_24B (0x2 << 4) +#define RT1308_I2S_DL_RX_SEL_32B (0x3 << 4) +#define RT1308_I2S_DL_RX_SEL_8B (0x4 << 4) +#define RT1308_I2S_DL_TX_SEL_MASK (0x7 << 0) +#define RT1308_I2S_DL_TX_SEL_SFT 0 +#define RT1308_I2S_DL_TX_SEL_16B (0x0 << 0) +#define RT1308_I2S_DL_TX_SEL_20B (0x1 << 0) +#define RT1308_I2S_DL_TX_SEL_24B (0x2 << 0) +#define RT1308_I2S_DL_TX_SEL_32B (0x3 << 0) +#define RT1308_I2S_DL_TX_SEL_8B (0x4 << 0) + +/* I2S Setting-2 (0x16) */ +#define RT1308_I2S_DL_SEL_MASK (0x7 << 24) +#define RT1308_I2S_DL_SEL_SFT 24 +#define RT1308_I2S_DL_SEL_16B (0x0 << 24) +#define RT1308_I2S_DL_SEL_20B (0x1 << 24) +#define RT1308_I2S_DL_SEL_24B (0x2 << 24) +#define RT1308_I2S_DL_SEL_32B (0x3 << 24) +#define RT1308_I2S_DL_SEL_8B (0x4 << 24) +#define RT1308_I2S_BCLK_MASK (0x1 << 14) +#define RT1308_I2S_BCLK_SFT 14 +#define RT1308_I2S_BCLK_NORMAL (0x0 << 14) +#define RT1308_I2S_BCLK_INV (0x1 << 14) + +/* Power Control-1 (0x32) */ +#define RT1308_POW_MBIAS20U (0x1 << 31) +#define RT1308_POW_MBIAS20U_BIT 31 +#define RT1308_POW_ALDO (0x1 << 30) +#define RT1308_POW_ALDO_BIT 30 +#define RT1308_POW_DBG (0x1 << 29) +#define RT1308_POW_DBG_BIT 29 +#define RT1308_POW_DACL (0x1 << 28) +#define RT1308_POW_DACL_BIT 28 +#define RT1308_POW_DAC1 (0x1 << 27) +#define RT1308_POW_DAC1_BIT 27 +#define RT1308_POW_CLK25M (0x1 << 26) +#define RT1308_POW_CLK25M_BIT 26 +#define RT1308_POW_ADC_R (0x1 << 25) +#define RT1308_POW_ADC_R_BIT 25 +#define RT1308_POW_ADC_L (0x1 << 24) +#define RT1308_POW_ADC_L_BIT 24 +#define RT1308_POW_DLDO (0x1 << 21) +#define RT1308_POW_DLDO_BIT 21 +#define RT1308_POW_VREF (0x1 << 20) +#define RT1308_POW_VREF_BIT 20 +#define RT1308_POW_MIXER_R (0x1 << 18) +#define RT1308_POW_MIXER_R_BIT 18 +#define RT1308_POW_MIXER_L (0x1 << 17) +#define RT1308_POW_MIXER_L_BIT 17 +#define RT1308_POW_MBIAS4U (0x1 << 16) +#define RT1308_POW_MBIAS4U_BIT 16 +#define RT1308_POW_PLL2_LDO_EN (0x1 << 12) +#define RT1308_POW_PLL2_LDO_EN_BIT 12 +#define RT1308_POW_PLL2B_EN (0x1 << 11) +#define RT1308_POW_PLL2B_EN_BIT 11 +#define RT1308_POW_PLL2F_EN (0x1 << 10) +#define RT1308_POW_PLL2F_EN_BIT 10 +#define RT1308_POW_PLL2F2_EN (0x1 << 9) +#define RT1308_POW_PLL2F2_EN_BIT 9 +#define RT1308_POW_PLL2B2_EN (0x1 << 8) +#define RT1308_POW_PLL2B2_EN_BIT 8 + +/* Power Control-2 (0x36) */ +#define RT1308_POW_PDB_SRC_BIT (0x1 << 27) +#define RT1308_POW_PDB_MN_BIT (0x1 << 25) +#define RT1308_POW_PDB_REG_BIT (0x1 << 24) + + +/* System Clock Source */ +enum { + RT1308_FS_SYS_S_MCLK, + RT1308_FS_SYS_S_BCLK, + RT1308_FS_SYS_S_PLL, + RT1308_FS_SYS_S_RCCLK, /* 25.0 MHz */ +}; + +/* PLL Source */ +enum { + RT1308_PLL_S_MCLK, + RT1308_PLL_S_BCLK, + RT1308_PLL_S_RCCLK, +}; + +enum { + RT1308_AIF1, + RT1308_AIFS +}; + +#endif /* end of _RT1308_H_ */ From 7c2b3629d09ddec810dc4c1d3a6657c32def8f71 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 1 Jul 2019 15:46:30 +0800 Subject: [PATCH 585/626] ALSA: hda: Fix a headphone detection issue when using SOF To save power, the hda hdmi driver in ASoC invokes snd_hdac_ext_bus_link_put to disable CORB/RIRB buffers DMA if there is no user of bus and invokes snd_hdac_ext_bus_link_get to set up CORB/RIRB buffers when it is used. Unsolicited responses is disabled in snd_hdac_bus_stop_cmd_io called by snd_hdac_ext_bus_link_put , but it is not enabled in snd_hdac_bus_init_cmd_io called by snd_hdac_ext_bus_link_get. So for put-get sequence, Unsolicited responses is disabled and headphone can't be detected by hda codecs. Now unsolicited responses is only enabled in snd_hdac_bus_reset_link which resets controller. The function is only called for setup of controller. This patch enables Unsolicited responses after RIRB is initialized in snd_hdac_bus_init_cmd_io which works together with snd_hdac_bus_reset_link to set up controller. Tested legacy hda driver and SOF driver on intel whiskeylake. Reviewed-by: Takashi Iwai Signed-off-by: Rander Wang Signed-off-by: Takashi Iwai --- sound/hda/hdac_controller.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index d6a91429c058..c24fc8d266a9 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -78,6 +78,8 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) snd_hdac_chip_writew(bus, RINTCNT, 1); /* enable rirb dma and response irq */ snd_hdac_chip_writeb(bus, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); + /* Accept unsolicited responses */ + snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io); @@ -416,9 +418,6 @@ int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset) return -EBUSY; } - /* Accept unsolicited responses */ - snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); - /* detect codecs */ if (!bus->codec_mask) { bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); From 559e92f78778a171adfb152f49a78e202f5b39df Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 29 Jun 2019 02:43:33 +0000 Subject: [PATCH 586/626] ASoC: madera: Remove duplicated include from cs47l35.c Remove duplicated include. Signed-off-by: YueHaibing Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l35.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index 511d0d6fa962..e3585c1dab3d 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include From 2d2e331697bfba9dcc59217b1fcbfa2c144f0659 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 2 Jul 2019 06:17:38 +0000 Subject: [PATCH 587/626] ASoC: rt1308: Fix platform_no_drv_owner.cocci warnings Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: YueHaibing Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index 619a630e982e..d673506c7c39 100755 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -884,7 +884,6 @@ static void rt1308_i2c_shutdown(struct i2c_client *client) static struct i2c_driver rt1308_i2c_driver = { .driver = { .name = "rt1308", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(rt1308_of_match), .acpi_match_table = ACPI_PTR(rt1308_acpi_match), }, From 7422104037773624d2a6cdb9becb68278befbd88 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 13:08:48 +0900 Subject: [PATCH 588/626] ASoC: au1x: psc-i2s.c: use devm_snd_soc_register_component() We have devm_xxx version of snd_soc_register_component, let's use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/au1x/psc-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 4a5a095076f4..076303f96b8c 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -340,16 +340,14 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) platform_set_drvdata(pdev, wd); - return snd_soc_register_component(&pdev->dev, &au1xpsc_i2s_component, - &wd->dai_drv, 1); + return devm_snd_soc_register_component(&pdev->dev, + &au1xpsc_i2s_component, &wd->dai_drv, 1); } static int au1xpsc_i2s_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); - snd_soc_unregister_component(&pdev->dev); - __raw_writel(0, I2S_CFG(wd)); wmb(); /* drain writebuffer */ __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); From cb9002a186329b35f32f74021551aecbfe9a696c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 13:09:00 +0900 Subject: [PATCH 589/626] ASoC: cirrus: ep93xx-i2s.c: use devm_snd_soc_register_component() We have devm_xxx version of snd_soc_register_component, let's use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 6ca899ba9484..0b4355e95f84 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -473,19 +473,17 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, info); - err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component, + err = devm_snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component, &ep93xx_i2s_dai, 1); if (err) goto fail_put_lrclk; err = devm_ep93xx_pcm_platform_register(&pdev->dev); if (err) - goto fail_unregister; + goto fail_put_lrclk; return 0; -fail_unregister: - snd_soc_unregister_component(&pdev->dev); fail_put_lrclk: clk_put(info->lrclk); fail_put_sclk: @@ -500,7 +498,6 @@ static int ep93xx_i2s_remove(struct platform_device *pdev) { struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); clk_put(info->lrclk); clk_put(info->sclk); clk_put(info->mclk); From 61c8a7d6ff11a31fc4ea47667c5f33119be7bcd3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 13:09:28 +0900 Subject: [PATCH 590/626] ASoC: rt5682: use devm_snd_soc_register_component() We have devm_xxx version of snd_soc_register_component, let's use it. This patch also removes related empty functions Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 78409dd11488..1ef470700ed5 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2662,15 +2662,9 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, } - return snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5682, - rt5682_dai, ARRAY_SIZE(rt5682_dai)); -} - -static int rt5682_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_component(&i2c->dev); - - return 0; + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_rt5682, + rt5682_dai, ARRAY_SIZE(rt5682_dai)); } static void rt5682_i2c_shutdown(struct i2c_client *client) @@ -2703,7 +2697,6 @@ static struct i2c_driver rt5682_i2c_driver = { .acpi_match_table = ACPI_PTR(rt5682_acpi_match), }, .probe = rt5682_i2c_probe, - .remove = rt5682_i2c_remove, .shutdown = rt5682_i2c_shutdown, .id_table = rt5682_i2c_id, }; From 35407f9ffd84560501f72ee3954344f8e5b49264 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 13:09:40 +0900 Subject: [PATCH 591/626] ASoC: ak4118: use devm_snd_soc_register_component() We have devm_xxx version of snd_soc_register_component, let's use it. This patch also removes related empty functions Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/ak4118.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/ak4118.c b/sound/soc/codecs/ak4118.c index ce419e8cf890..f44d9a4a8507 100644 --- a/sound/soc/codecs/ak4118.c +++ b/sound/soc/codecs/ak4118.c @@ -400,14 +400,8 @@ static int ak4118_i2c_probe(struct i2c_client *i2c, return ret; } - return snd_soc_register_component(&i2c->dev, &soc_component_drv_ak4118, - &ak4118_dai, 1); -} - -static int ak4118_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_component(&i2c->dev); - return 0; + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_drv_ak4118, &ak4118_dai, 1); } static const struct of_device_id ak4118_of_match[] = { @@ -429,7 +423,6 @@ static struct i2c_driver ak4118_i2c_driver = { }, .id_table = ak4118_id_table, .probe = ak4118_i2c_probe, - .remove = ak4118_i2c_remove, }; module_i2c_driver(ak4118_i2c_driver); From dcbe6ed32e06b7811e082806a9c0f84d3a238d18 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 13:09:50 +0900 Subject: [PATCH 592/626] ASoC: cros_ec_codec: use devm_snd_soc_register_component() We have devm_xxx version of snd_soc_register_component, let's use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/cros_ec_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index 99a3af8a15ff..0ac3e520653f 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -413,7 +413,7 @@ static int cros_ec_codec_platform_probe(struct platform_device *pd) platform_set_drvdata(pd, codec_data); - return snd_soc_register_component(dev, &cros_ec_component_driver, + return devm_snd_soc_register_component(dev, &cros_ec_component_driver, cros_ec_dai, ARRAY_SIZE(cros_ec_dai)); } From 4b9b73b86571e8a03fb09232ff72177e66bf9ef9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Jun 2019 13:10:31 +0900 Subject: [PATCH 593/626] ASoC: pxa: pxa2xx-ac97.c: use devm_snd_soc_register_component() We have devm_xxx version of snd_soc_register_component, let's use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-ac97.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 687a8f1f9e0d..bf28187315db 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -250,7 +250,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) * driver to do interesting things with the clocking to get us up * and running. */ - return snd_soc_register_component(&pdev->dev, &pxa_ac97_component, + return devm_snd_soc_register_component(&pdev->dev, &pxa_ac97_component, pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver)); } @@ -258,7 +258,6 @@ static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) { struct ac97_controller *ctrl = platform_get_drvdata(pdev); - snd_soc_unregister_component(&pdev->dev); snd_ac97_controller_unregister(ctrl); pxa2xx_ac97_hw_remove(pdev); return 0; From cec5b01f8f1c6064037f3181e7690e3765ed995b Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Wed, 19 Jun 2019 18:18:33 +0800 Subject: [PATCH 594/626] ASoC: max98357a: avoid speaker pop when playback startup Loud speaker pop happens during playback even when in slience playback. Specify Max98357a amp delay times to make sure clocks are always earlier than sdmode on. Signed-off-by: Mac Chiang Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/max98357a.txt | 4 ++ sound/soc/codecs/max98357a.c | 55 ++++++++++++++++--- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/max98357a.txt b/Documentation/devicetree/bindings/sound/max98357a.txt index 28645a2ff885..4bce14ce806f 100644 --- a/Documentation/devicetree/bindings/sound/max98357a.txt +++ b/Documentation/devicetree/bindings/sound/max98357a.txt @@ -9,6 +9,10 @@ Optional properties: - sdmode-gpios : GPIO specifier for the chip's SD_MODE pin. If this option is not specified then driver does not manage the pin state (e.g. chip is always on). +- sdmode-delay : specify delay time for SD_MODE pin. + If this option is specified, which means it's required i2s clocks + ready before SD_MODE is unmuted in order to avoid the speaker pop noise. + It's observed that 5ms is sufficient. Example: diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index 6f724c9a3867..6f0e28f903bf 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -19,24 +19,42 @@ #include #include +struct max98357a_priv { + struct delayed_work enable_sdmode_work; + struct gpio_desc *sdmode; + unsigned int sdmode_delay; +}; + +static void max98357a_enable_sdmode_work(struct work_struct *work) +{ + struct max98357a_priv *max98357a = + container_of(work, struct max98357a_priv, + enable_sdmode_work.work); + + gpiod_set_value(max98357a->sdmode, 1); +} + static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai); + struct max98357a_priv *max98357a = snd_soc_dai_get_drvdata(dai); - if (!sdmode) + if (!max98357a->sdmode) return 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - gpiod_set_value(sdmode, 1); + queue_delayed_work(system_power_efficient_wq, + &max98357a->enable_sdmode_work, + msecs_to_jiffies(max98357a->sdmode_delay)); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - gpiod_set_value(sdmode, 0); + cancel_delayed_work_sync(&max98357a->enable_sdmode_work); + gpiod_set_value(max98357a->sdmode, 0); break; } @@ -90,14 +108,33 @@ static struct snd_soc_dai_driver max98357a_dai_driver = { static int max98357a_platform_probe(struct platform_device *pdev) { - struct gpio_desc *sdmode; + struct max98357a_priv *max98357a; + int ret; - sdmode = devm_gpiod_get_optional(&pdev->dev, + max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL); + + if (!max98357a) + return -ENOMEM; + + max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev, "sdmode", GPIOD_OUT_LOW); - if (IS_ERR(sdmode)) - return PTR_ERR(sdmode); - dev_set_drvdata(&pdev->dev, sdmode); + if (IS_ERR(max98357a->sdmode)) + return PTR_ERR(max98357a->sdmode); + + ret = device_property_read_u32(&pdev->dev, "sdmode-delay", + &max98357a->sdmode_delay); + + if (ret) { + max98357a->sdmode_delay = 0; + dev_dbg(&pdev->dev, + "no optional property 'sdmode-delay' found, default: no delay\n"); + } + + dev_set_drvdata(&pdev->dev, max98357a); + + INIT_DELAYED_WORK(&max98357a->enable_sdmode_work, + max98357a_enable_sdmode_work); return devm_snd_soc_register_component(&pdev->dev, &max98357a_component_driver, From 094380ea2bf9f0fa7d63e67bf500b8c77e8d1910 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 3 Jul 2019 14:07:48 +0200 Subject: [PATCH 595/626] ASoC: meson: axg-tdm-formatter: add reset to the bindings documentation Add an optional reset property to the tdm formatter bindings. The dedicated reset line is present on some SoC families, such as the g12a. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190703120749.32341-2-jbrunet@baylibre.com Signed-off-by: Mark Brown --- .../bindings/sound/amlogic,axg-tdm-formatters.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt index 3b94a715a0b9..8835a43edfbb 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt @@ -15,11 +15,15 @@ Required properties: * "lrclk" : sample clock * "lrclk_sel": sample clock input multiplexer -Example of TDMOUT_A on the A113 SoC: +Optional property: +- resets: phandle to the dedicated reset line of the tdm formatter. + +Example of TDMOUT_A on the S905X2 SoC: tdmout_a: audio-controller@500 { compatible = "amlogic,axg-tdmout"; reg = <0x0 0x500 0x0 0x40>; + resets = <&clkc_audio AUD_RESET_TDMOUT_A>; clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>, <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>, <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>, From 751bd5db52604f3f71d54dbad82707ef2475b707 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 3 Jul 2019 14:07:49 +0200 Subject: [PATCH 596/626] ASoC: meson: axg-tdm-formatter: add reset Add the optional reset line handling which is present on the new SoC families, such as the g12a. Triggering this reset is not critical but it helps solve a channel shift issue on the g12a. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190703120749.32341-3-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm-formatter.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index 0c6cce5c5773..2e498201139f 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "axg-tdm-formatter.h" @@ -20,6 +21,7 @@ struct axg_tdm_formatter { struct clk *lrclk; struct clk *sclk_sel; struct clk *lrclk_sel; + struct reset_control *reset; bool enabled; struct regmap *map; }; @@ -75,6 +77,24 @@ static int axg_tdm_formatter_enable(struct axg_tdm_formatter *formatter) if (formatter->enabled) return 0; + /* + * On the g12a (and possibly other SoCs), when a stream using + * multiple lanes is restarted, it will sometimes not start + * from the first lane, but randomly from another used one. + * The result is an unexpected and random channel shift. + * + * The hypothesis is that an HW counter is not properly reset + * and the formatter simply starts on the lane it stopped + * before. Unfortunately, there does not seems to be a way to + * reset this through the registers of the block. + * + * However, the g12a has indenpendent reset lines for each audio + * devices. Using this reset before each start solves the issue. + */ + ret = reset_control_reset(formatter->reset); + if (ret) + return ret; + /* * If sclk is inverted, invert it back and provide the inversion * required by the formatter @@ -306,6 +326,15 @@ int axg_tdm_formatter_probe(struct platform_device *pdev) return ret; } + /* Formatter dedicated reset line */ + formatter->reset = reset_control_get_optional_exclusive(dev, NULL); + if (IS_ERR(formatter->reset)) { + ret = PTR_ERR(formatter->reset); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get reset: %d\n", ret); + return ret; + } + return devm_snd_soc_register_component(dev, drv->component_drv, NULL, 0); } From 74b35a74f80e02bdd69db9cf96d3f4fe78b67064 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 3 Jul 2019 13:30:02 +0100 Subject: [PATCH 597/626] ASoC: core: Return -ENOTSUPP from set_channel_map() if no operation provided It makes it easier for common code to work with snd_soc_dai_set_channel_map() by distinguishing between operation not being supported and an error. This is done inline with others snd_soc_dai.* apis. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20190703123002.12427-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b9061cd8d787..c0a774d0a5ff 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2614,7 +2614,7 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, rx_num, rx_slot); else - return -EINVAL; + return -ENOTSUPP; } EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); From 9aa0cf79568e7078c32710034b0df8946db6cdad Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 3 Jul 2019 13:31:02 +0100 Subject: [PATCH 598/626] ASoC: qdsp6: q6afe-dai: Add missing Slimbus0 audio route For some reason SLIMBus RX0 playback is not added to audio routes. This patch adds the missing route. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20190703123102.12626-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6afe-dai.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index dc645ba4d8d0..c1a7624eaf17 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -447,6 +447,7 @@ static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai, static const struct snd_soc_dapm_route q6afe_dapm_routes[] = { {"HDMI Playback", NULL, "HDMI_RX"}, {"Display Port Playback", NULL, "DISPLAY_PORT_RX"}, + {"Slimbus Playback", NULL, "SLIMBUS_0_RX"}, {"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"}, {"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"}, {"Slimbus3 Playback", NULL, "SLIMBUS_3_RX"}, From 1bcc1fd64e4dd903f4d868a9e053986e3b102713 Mon Sep 17 00:00:00 2001 From: Wen Yang Date: Thu, 4 Jul 2019 16:38:50 +0800 Subject: [PATCH 599/626] ASoC: audio-graph-card: fix use-after-free in graph_for_each_link After calling of_node_put() on the codec_ep and codec_port variables, they are still being used, which may result in use-after-free. We fix this issue by calling of_node_put() after the last usage. Fixes: fce9b90c1ab7 ("ASoC: audio-graph-card: cleanup DAI link loop method - step2") Signed-off-by: Wen Yang Cc: Liam Girdwood Cc: Mark Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: Kuninori Morimoto Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/1562229530-8121-1-git-send-email-wen.yang99@zte.com.cn Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index ec7e673ba475..70ed28d97d49 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -435,9 +435,6 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, codec_ep = of_graph_get_remote_endpoint(cpu_ep); codec_port = of_get_parent(codec_ep); - of_node_put(codec_ep); - of_node_put(codec_port); - /* get convert-xxx property */ memset(&adata, 0, sizeof(adata)); graph_parse_convert(dev, codec_ep, &adata); @@ -457,6 +454,9 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, else ret = func_noml(priv, cpu_ep, codec_ep, li); + of_node_put(codec_ep); + of_node_put(codec_port); + if (ret < 0) return ret; From d07a9a4f66e944fcc900812cbc2f6817bde6a43d Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Thu, 4 Jul 2019 16:02:10 +0800 Subject: [PATCH 600/626] ALSA: hda/realtek - Headphone Mic can't record after S3 Dell headset mode platform with ALC236. It doesn't recording after system resume from S3. S3 mode was deep. s2idle was not has this issue. S3 deep will cut of codec power. So, the register will back to default after resume back. This patch will solve this issue. Signed-off-by: Kailang Yang Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 48f3c5b8d6e9..0f776444ab86 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3268,6 +3268,7 @@ static void alc256_init(struct hda_codec *codec) alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */ alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15); + alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/ } static void alc256_shutup(struct hda_codec *codec) @@ -7838,7 +7839,6 @@ static int patch_alc269(struct hda_codec *codec) spec->shutup = alc256_shutup; spec->init_hook = alc256_init; spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */ - alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/ break; case 0x10ec0257: spec->codec_variant = ALC269_TYPE_ALC257; From 335399362a6edeec5a365ed0fbb0b6902cacc4e4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 4 Jul 2019 13:44:25 +0100 Subject: [PATCH 601/626] ALSA: hda/ca0132 - remove redundant assignment to variable 'changed' The variable 'changed' is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index de61179c91e2..49adfc4ef5de 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -5993,7 +5993,7 @@ static int ca0132_alt_volume_put(struct snd_kcontrol *kcontrol, int ch = get_amp_channels(kcontrol); long *valp = ucontrol->value.integer.value; hda_nid_t vnid = 0; - int changed = 1; + int changed; switch (nid) { case 0x02: From ca95c7bf3d29716916baccdc77c3c2284b703069 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 4 Jul 2019 16:31:12 +0200 Subject: [PATCH 602/626] ALSA: usb-audio: Fix parse of UAC2 Extension Units Extension Unit (XU) is used to have a compatible layout with Processing Unit (PU) on UAC1, and the usb-audio driver code assumed it for parsing the descriptors. Meanwhile, on UAC2, XU became slightly incompatible with PU; namely, XU has a one-byte bmControls bitmap while PU has two bytes bmControls bitmap. This incompatibility results in the read of a wrong address for the last iExtension field, which ended up with an incorrect string for the mixer element name, as recently reported for Focusrite Scarlett 18i20 device. This patch corrects this misalignment by introducing a couple of new macros and calling them depending on the descriptor type. Fixes: 23caaf19b11e ("ALSA: usb-mixer: Add support for Audio Class v2.0") Reported-by: Stefan Sauer Cc: Signed-off-by: Takashi Iwai --- include/uapi/linux/usb/audio.h | 37 ++++++++++++++++++++++++++++++++++ sound/usb/mixer.c | 16 +++++++++------ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h index ddc5396800aa..76b7c3f6cd0d 100644 --- a/include/uapi/linux/usb/audio.h +++ b/include/uapi/linux/usb/audio.h @@ -450,6 +450,43 @@ static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_desc } } +/* + * Extension Unit (XU) has almost compatible layout with Processing Unit, but + * on UAC2, it has a different bmControls size (bControlSize); it's 1 byte for + * XU while 2 bytes for PU. The last iExtension field is a one-byte index as + * well as iProcessing field of PU. + */ +static inline __u8 uac_extension_unit_bControlSize(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return desc->baSourceID[desc->bNrInPins + 4]; + case UAC_VERSION_2: + return 1; /* in UAC2, this value is constant */ + case UAC_VERSION_3: + return 4; /* in UAC3, this value is constant */ + default: + return 1; + } +} + +static inline __u8 uac_extension_unit_iExtension(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_extension_unit_bControlSize(desc, protocol); + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return *(uac_processing_unit_bmControls(desc, protocol) + + control_size); + case UAC_VERSION_3: + return 0; /* UAC3 does not have this field */ + } +} + /* 4.5.2 Class-Specific AS Interface Descriptor */ struct uac1_as_header_descriptor { __u8 bLength; /* in bytes: 7 */ diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index e003b5e7b01a..ac121b10c51c 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2318,7 +2318,7 @@ static struct procunit_info extunits[] = { */ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list, - char *name) + bool extension_unit) { struct uac_processing_unit_descriptor *desc = raw_desc; int num_ins; @@ -2335,6 +2335,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, static struct procunit_info default_info = { 0, NULL, default_value_info }; + const char *name = extension_unit ? + "Extension Unit" : "Processing Unit"; if (desc->bLength < 13) { usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); @@ -2448,7 +2450,10 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, } else if (info->name) { strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); } else { - nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol); + if (extension_unit) + nameid = uac_extension_unit_iExtension(desc, state->mixer->protocol); + else + nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol); len = 0; if (nameid) len = snd_usb_copy_string_desc(state->chip, @@ -2481,10 +2486,10 @@ static int parse_audio_processing_unit(struct mixer_build *state, int unitid, case UAC_VERSION_2: default: return build_audio_procunit(state, unitid, raw_desc, - procunits, "Processing Unit"); + procunits, false); case UAC_VERSION_3: return build_audio_procunit(state, unitid, raw_desc, - uac3_procunits, "Processing Unit"); + uac3_procunits, false); } } @@ -2495,8 +2500,7 @@ static int parse_audio_extension_unit(struct mixer_build *state, int unitid, * Note that we parse extension units with processing unit descriptors. * That's ok as the layout is the same. */ - return build_audio_procunit(state, unitid, raw_desc, - extunits, "Extension Unit"); + return build_audio_procunit(state, unitid, raw_desc, extunits, true); } /* From bb26e0c636d42f9eda81b1cd863e59e42669dce7 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Fri, 5 Jul 2019 08:27:33 +0530 Subject: [PATCH 603/626] ALSA: asihpi: Remove unneeded variable change this patch fixes below issue reported by coccicheck sound/pci/asihpi/asihpi.c:1558:5-11: Unneeded variable: "change". Return "1" on line 1564 Signed-off-by: Hariprasad Kelam Signed-off-by: Takashi Iwai --- sound/pci/asihpi/asihpi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 32b2f9802479..0b35fb7e7a78 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -1532,7 +1532,6 @@ static int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol, static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int change; u32 h_control = kcontrol->private_value; short an_gain_mB[HPI_MAX_CHANNELS]; @@ -1543,9 +1542,8 @@ static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol, /* change = asihpi->mixer_volume[addr][0] != left || asihpi->mixer_volume[addr][1] != right; */ - change = 1; hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB)); - return change; + return 1; } static const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0); @@ -1568,13 +1566,12 @@ static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u32 h_control = kcontrol->private_value; - int change = 1; /* HPI currently only supports all or none muting of multichannel volume ALSA Switch element has opposite sense to HPI mute: on==unmuted, off=muted */ int mute = ucontrol->value.integer.value[0] ? 0 : HPI_BITMASK_ALL_CHANNELS; hpi_handle_error(hpi_volume_set_mute(h_control, mute)); - return change; + return 1; } static int snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, From 774a075ab5140bb4504e6026bf327021926c3e65 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 3 Jul 2019 14:35:12 +0200 Subject: [PATCH 604/626] ALSA: hda: Simplify snd_hdac_refresh_widgets() Along with the recent fix for the races of snd_hdac_refresh_widgets() it turned out that the instantiation of widgets sysfs at snd_hdac_sysfs_reinit() could cause a race. The race itself was already covered later by extending the mutex protection range, the commit 98482377dc72 ("ALSA: hda: Fix widget_mutex incomplete protection"), but this also indicated that the call of *_reinit() is basically superfluous, as the widgets shall be created sooner or later from snd_hdac_device_register(). This patch removes the redundant call of snd_hdac_sysfs_reinit() at first. By this removal, the sysfs argument itself in snd_hdac_refresh_widgets() becomes superfluous, too, because the only case sysfs=false is always with codec->widgets=NULL. So, we drop this redundant argument as well. Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 2 +- sound/hda/hdac_device.c | 13 +++++-------- sound/hda/hdac_sysfs.c | 2 +- sound/pci/hda/hda_codec.c | 2 +- sound/soc/codecs/hdac_hdmi.c | 2 +- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index e8346784cf3f..f475293d0668 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -120,7 +120,7 @@ void snd_hdac_device_unregister(struct hdac_device *codec); int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name); int snd_hdac_codec_modalias(struct hdac_device *hdac, char *buf, size_t size); -int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs); +int snd_hdac_refresh_widgets(struct hdac_device *codec); unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, unsigned int verb, unsigned int parm); diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 11050bfd8068..a265c1d68876 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -89,7 +89,7 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus, fg = codec->afg ? codec->afg : codec->mfg; - err = snd_hdac_refresh_widgets(codec, false); + err = snd_hdac_refresh_widgets(codec); if (err < 0) goto error; @@ -394,9 +394,8 @@ static void setup_fg_nodes(struct hdac_device *codec) /** * snd_hdac_refresh_widgets - Reset the widget start/end nodes * @codec: the codec object - * @sysfs: re-initialize sysfs tree, too */ -int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs) +int snd_hdac_refresh_widgets(struct hdac_device *codec) { hda_nid_t start_nid; int nums, err = 0; @@ -414,11 +413,9 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs) goto unlock; } - if (sysfs) { - err = hda_widget_sysfs_reinit(codec, start_nid, nums); - if (err < 0) - goto unlock; - } + err = hda_widget_sysfs_reinit(codec, start_nid, nums); + if (err < 0) + goto unlock; codec->num_nodes = nums; codec->start_nid = start_nid; diff --git a/sound/hda/hdac_sysfs.c b/sound/hda/hdac_sysfs.c index 909d5ef1179c..e56e83325903 100644 --- a/sound/hda/hdac_sysfs.c +++ b/sound/hda/hdac_sysfs.c @@ -428,7 +428,7 @@ int hda_widget_sysfs_reinit(struct hdac_device *codec, int i; if (!codec->widgets) - return hda_widget_sysfs_init(codec); + return 0; tree = kmemdup(codec->widgets, sizeof(*tree), GFP_KERNEL); if (!tree) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index fcdf2cd3783b..d1a0e0de80ac 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1016,7 +1016,7 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec) hda_nid_t fg; int err; - err = snd_hdac_refresh_widgets(&codec->core, true); + err = snd_hdac_refresh_widgets(&codec->core); if (err < 0) return err; diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 660e0587f399..6302ad5b7128 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -2043,7 +2043,7 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) "Failed in parse and map nid with err: %d\n", ret); return ret; } - snd_hdac_refresh_widgets(hdev, true); + snd_hdac_refresh_widgets(hdev); /* ASoC specific initialization */ ret = devm_snd_soc_register_component(&hdev->dev, &hdmi_hda_codec, From 388b00f045180179fedff4b108d40a0192684cda Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 5 Jul 2019 10:57:04 +0100 Subject: [PATCH 605/626] ALSA: cs4281: remove redundant assignment to variable val and remove a goto The variable val is being assigned with a value that is never read and it is being updated later with a new value. The assignment is redundant and can be removed. Also remove a goto statement and a label and replace with a break statement. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/cs4281.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 15bbf9564c82..d271cb881948 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -709,7 +709,7 @@ static int snd_cs4281_trigger(struct snd_pcm_substream *substream, int cmd) static unsigned int snd_cs4281_rate(unsigned int rate, unsigned int *real_rate) { - unsigned int val = ~0; + unsigned int val; if (real_rate) *real_rate = rate; @@ -722,9 +722,8 @@ static unsigned int snd_cs4281_rate(unsigned int rate, unsigned int *real_rate) case 44100: return 1; case 48000: return 0; default: - goto __variable; + break; } - __variable: val = 1536000 / rate; if (real_rate) *real_rate = 1536000 / val; From c150266f592bc0baf1de515ca793ef839f645fc8 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 4 Jul 2019 17:54:10 +0100 Subject: [PATCH 606/626] ASoC: wcd9335: remove multiple defines. Found during review that there are multiple defines of same constants. This patch removes them! Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20190704165410.7173-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 85737fe54474..1bbbe421b999 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -86,11 +86,6 @@ #define WCD9335_DEC_PWR_LVL_HP 0x04 #define WCD9335_DEC_PWR_LVL_DF 0x00 -#define TX_HPF_CUT_OFF_FREQ_MASK 0x60 -#define CF_MIN_3DB_4HZ 0x0 -#define CF_MIN_3DB_75HZ 0x1 -#define CF_MIN_3DB_150HZ 0x2 - #define WCD9335_SLIM_RX_CH(p) \ {.port = p + WCD9335_RX_START, .shift = p,} From 590eb2f4ef94cb3f3e73345c6db4de97c9cd539e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 5 Jul 2019 08:53:03 +0100 Subject: [PATCH 607/626] ASoC: rt5665: remove redundant assignment to variable idx The variable idx is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190705075303.14692-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5665.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 87263317085a..c050d84a6916 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -1478,7 +1478,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component); - int pd, idx = -EINVAL; + int pd, idx; pd = rl6231_get_pre_div(rt5665->regmap, RT5665_ADDA_CLK_1, RT5665_I2S_PD1_SFT); From 1fe08602d1179e7bfb2e805b22e8f57f4916c51e Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 3 Jul 2019 20:48:11 +0200 Subject: [PATCH 608/626] ASoC: sunxi: sun50i-codec-analog: Add earpiece This adds the necessary registers and audio routes to play audio using the Earpiece, that's supported on the A64. Signed-off-by: Luca Weiss Reviewed-by: Chen-Yu Tsai Link: https://lore.kernel.org/r/20190703184814.27191-1-luca@z3ntu.xyz Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-codec-analog.c | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index d105c90c3706..6d1de565350e 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c @@ -49,6 +49,15 @@ #define SUN50I_ADDA_OR_MIX_CTRL_DACR 1 #define SUN50I_ADDA_OR_MIX_CTRL_DACL 0 +#define SUN50I_ADDA_EARPIECE_CTRL0 0x03 +#define SUN50I_ADDA_EARPIECE_CTRL0_EAR_RAMP_TIME 4 +#define SUN50I_ADDA_EARPIECE_CTRL0_ESPSR 0 + +#define SUN50I_ADDA_EARPIECE_CTRL1 0x04 +#define SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN 7 +#define SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE 6 +#define SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL 0 + #define SUN50I_ADDA_LINEOUT_CTRL0 0x05 #define SUN50I_ADDA_LINEOUT_CTRL0_LEN 7 #define SUN50I_ADDA_LINEOUT_CTRL0_REN 6 @@ -172,6 +181,10 @@ static const DECLARE_TLV_DB_RANGE(sun50i_codec_lineout_vol_scale, 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0), ); +static const DECLARE_TLV_DB_RANGE(sun50i_codec_earpiece_vol_scale, + 0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), + 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0), +); /* volume / mute controls */ static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = { @@ -225,6 +238,15 @@ static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = { SUN50I_ADDA_LINEOUT_CTRL0_LEN, SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0), + SOC_SINGLE_TLV("Earpiece Playback Volume", + SUN50I_ADDA_EARPIECE_CTRL1, + SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL, 0x1f, 0, + sun50i_codec_earpiece_vol_scale), + + SOC_SINGLE("Earpiece Playback Switch", + SUN50I_ADDA_EARPIECE_CTRL1, + SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0), + }; static const char * const sun50i_codec_hp_src_enum_text[] = { @@ -257,6 +279,20 @@ static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = { sun50i_codec_lineout_src_enum), }; +static const char * const sun50i_codec_earpiece_src_enum_text[] = { + "DACR", "DACL", "Right Mixer", "Left Mixer", +}; + +static SOC_ENUM_SINGLE_DECL(sun50i_codec_earpiece_src_enum, + SUN50I_ADDA_EARPIECE_CTRL0, + SUN50I_ADDA_EARPIECE_CTRL0_ESPSR, + sun50i_codec_earpiece_src_enum_text); + +static const struct snd_kcontrol_new sun50i_codec_earpiece_src[] = { + SOC_DAPM_ENUM("Earpiece Source Playback Route", + sun50i_codec_earpiece_src_enum), +}; + static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { /* DAC */ SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL, @@ -285,6 +321,12 @@ static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src), SND_SOC_DAPM_OUTPUT("LINEOUT"), + SND_SOC_DAPM_MUX("Earpiece Source Playback Route", + SND_SOC_NOPM, 0, 0, sun50i_codec_earpiece_src), + SND_SOC_DAPM_OUT_DRV("Earpiece Amp", SUN50I_ADDA_EARPIECE_CTRL1, + SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("EARPIECE"), + /* Microphone inputs */ SND_SOC_DAPM_INPUT("MIC1"), @@ -388,6 +430,14 @@ static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = { { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" }, { "LINEOUT", NULL, "Line Out Source Playback Route" }, + + /* Earpiece Routes */ + { "Earpiece Source Playback Route", "DACL", "Left DAC" }, + { "Earpiece Source Playback Route", "DACR", "Right DAC" }, + { "Earpiece Source Playback Route", "Left Mixer", "Left Mixer" }, + { "Earpiece Source Playback Route", "Right Mixer", "Right Mixer" }, + { "Earpiece Amp", NULL, "Earpiece Source Playback Route" }, + { "EARPIECE", NULL, "Earpiece Amp" }, }; static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = { From b90bab3b1b1b6c56dd6f9d5c960932239f36f6d3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 5 Jul 2019 08:16:37 +0000 Subject: [PATCH 609/626] ASoC: SOF: debug: fix possible memory leak in sof_dfsentry_write() 'string' is malloced in sof_dfsentry_write() and should be freed before leaving from the error handling cases, otherwise it will cause memory leak. Fixes: 091c12e1f50c ("ASoC: SOF: debug: add new debugfs entries for IPC flood test") Signed-off-by: Wei Yongjun Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20190705081637.157169-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 54bb53bfc81b..2388477a965e 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -162,7 +162,7 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, else ret = kstrtoul(string, 0, &ipc_count); if (ret < 0) - return ret; + goto out; /* limit max duration/ipc count for flood test */ if (flood_duration_test) { @@ -191,7 +191,7 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, "error: debugfs write failed to resume %d\n", ret); pm_runtime_put_noidle(sdev->dev); - return ret; + goto out; } /* flood test */ From e62bccf8a5ec47768ae2600dc880b148cce19f1b Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 2 Jul 2019 16:24:26 +0300 Subject: [PATCH 610/626] ASoC: hdac_hdmi: report codec link up/down status to bus Report codec power status to the HDA codec bus from runtime pm suspend and resume callbacks. This is required to implement runtime idle logic that relies on 'codec_powered' field of hdac_bus to be maintained for all codecs. Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20190702132428.13129-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index c9f9820968bb..47eee18b66a3 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -2088,6 +2088,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) return -EIO; } + snd_hdac_codec_link_down(hdev); snd_hdac_ext_bus_link_put(bus, hlink); snd_hdac_display_power(bus, hdev->addr, false); @@ -2114,6 +2115,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev) } snd_hdac_ext_bus_link_get(bus, hlink); + snd_hdac_codec_link_up(hdev); snd_hdac_display_power(bus, hdev->addr, true); From 62fde9772dd8400bc407de8822ede56b5f2f67f1 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 2 Jul 2019 16:24:27 +0300 Subject: [PATCH 611/626] ASoC: SOF: add runtime idle callback Add ability to implement a SOF device level runtime idle callback. Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20190702132428.13129-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 1 + sound/soc/sof/ops.h | 8 ++++++++ sound/soc/sof/pm.c | 8 ++++++++ sound/soc/sof/sof-acpi-dev.c | 2 +- sound/soc/sof/sof-pci-dev.c | 2 +- sound/soc/sof/sof-priv.h | 2 ++ 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 73d7cc08afc2..d9c17146200b 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -457,6 +457,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state); int hda_dsp_resume(struct snd_sof_dev *sdev); int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state); int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); +int hda_dsp_runtime_idle(struct snd_sof_dev *sdev); int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags); void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 45a3d1091163..b9bdf45889da 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -134,6 +134,14 @@ static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev, return 0; } +static inline int snd_sof_dsp_runtime_idle(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev)->runtime_idle) + return sof_ops(sdev)->runtime_idle(sdev); + + return 0; +} + static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev) { if (sof_ops(sdev)->set_hw_params_upon_resume) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 8eeb3a1029f2..278abfd10490 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -394,6 +394,14 @@ int snd_sof_runtime_suspend(struct device *dev) } EXPORT_SYMBOL(snd_sof_runtime_suspend); +int snd_sof_runtime_idle(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + + return snd_sof_dsp_runtime_idle(sdev); +} +EXPORT_SYMBOL(snd_sof_runtime_idle); + int snd_sof_runtime_resume(struct device *dev) { return sof_resume(dev, true); diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index c8dafb1ac54e..ea7b8b895412 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -116,7 +116,7 @@ static const struct sof_dev_desc sof_acpi_cherrytrail_desc = { static const struct dev_pm_ops sof_acpi_pm = { SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, - NULL) + snd_sof_runtime_idle) }; static void sof_acpi_probe_complete(struct device *dev) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index e2b19782f01a..65d1bac4c6b8 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -206,7 +206,7 @@ static const struct sof_dev_desc kbl_desc = { static const struct dev_pm_ops sof_pci_pm = { SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, - NULL) + snd_sof_runtime_idle) }; static void sof_pci_probe_complete(struct device *dev) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 58621db4fd31..b8c0b2a22684 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -176,6 +176,7 @@ struct snd_sof_dsp_ops { int (*runtime_suspend)(struct snd_sof_dev *sof_dev, int state); /* optional */ int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */ + int (*runtime_idle)(struct snd_sof_dev *sof_dev); /* optional */ int (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ /* DSP clocking */ @@ -446,6 +447,7 @@ int snd_sof_device_remove(struct device *dev); int snd_sof_runtime_suspend(struct device *dev); int snd_sof_runtime_resume(struct device *dev); +int snd_sof_runtime_idle(struct device *dev); int snd_sof_resume(struct device *dev); int snd_sof_suspend(struct device *dev); From 87a6fe80d56be85bda093c4dd8a3e6535bda7e4a Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 2 Jul 2019 16:24:28 +0300 Subject: [PATCH 612/626] ASoC: SOF: Intel: implement runtime idle for CNL/APL Implement runtime idle for CNL/APL devices using similar runtime PM idle logic as the Intel AZX HDA driver. If any HDA codecs are powered when runtime suspend request comes, return -EBUSY. By doing this, strict ordering is enforced between HDA codec and the HDA controller. Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20190702132428.13129-4-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 1 + sound/soc/sof/intel/cnl.c | 1 + sound/soc/sof/intel/hda-dsp.c | 13 +++++++++++++ 3 files changed, 15 insertions(+) diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 43d1c9f31ec4..fd2e26d79796 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -93,6 +93,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .resume = hda_dsp_resume, .runtime_suspend = hda_dsp_runtime_suspend, .runtime_resume = hda_dsp_runtime_resume, + .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, }; EXPORT_SYMBOL(sof_apl_ops); diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 3840f81767fa..f2b392998f20 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -251,6 +251,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .resume = hda_dsp_resume, .runtime_suspend = hda_dsp_runtime_suspend, .runtime_resume = hda_dsp_runtime_resume, + .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, }; EXPORT_SYMBOL(sof_cnl_ops); diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index f2c5a12db930..91de4785b6a3 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -418,6 +418,19 @@ int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) return hda_resume(sdev); } +int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) +{ + struct hdac_bus *hbus = sof_to_bus(sdev); + + if (hbus->codec_powered) { + dev_dbg(sdev->dev, "some codecs still powered (%08X), not idle\n", + (unsigned int)hbus->codec_powered); + return -EBUSY; + } + + return 0; +} + int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state) { /* stop hda controller and power dsp off */ From 097f8ba3873dcbd2f55c627ed2fe0b13845e53cd Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 14:20:06 +0900 Subject: [PATCH 613/626] ALSA: bebob: fix wrong reference count for stream functionality at error path of rawmidi interface In IEC 61883-6, several types of sampling data can be multiplexed into payload of common isochronous packet (CIP). For typical audio and music units, PCM samples and MIDI messages are multiplexed into one packet streaming. ALSA bebob driver allows applications of rawmidi interface to start packet streaming for transmission of MIDI messages. However at error path, the reference count of stream functionality is not operated correctly. This can brings a bug that packet streaming is not stopped when all referrers release the count. This commit fixes the bug. Fixes: ac2888b958f2 ("ALSA: bebob: configure sampling transfer frequency in pcm.hw_params callback") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_midi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index f7db1f7bce86..f903271e93d0 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -22,6 +22,8 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err >= 0) { ++bebob->substreams_counter; err = snd_bebob_stream_start_duplex(bebob); + if (err < 0) + --bebob->substreams_counter; } mutex_unlock(&bebob->mutex); if (err < 0) From 2e9f17e34eb7b728d4cd9ec474c3c5a9a6685298 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 14:20:07 +0900 Subject: [PATCH 614/626] ALSA: fireworks: fix wrong reference count for stream functionality at error path of rawmidi interface In IEC 61883-6, several types of sampling data can be multiplexed into payload of common isochronous packet (CIP). For typical audio and music units, PCM samples and MIDI messages are multiplexed into one packet streaming. ALSA fireworks driver allows applications of rawmidi interface to start packet streaming for transmission of MIDI messages. However at error path, the reference count of stream functionality is not operated correctly. This can brings a bug that packet streaming is not stopped when all referrers release the count. This commit fixes the bug. Fixes: 3d7250667ea9 ("ALSA: fireworks: configure sampling transfer frequency in pcm.hw_params callback") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_midi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c index 6d3d942e2dce..fd17777981e4 100644 --- a/sound/firewire/fireworks/fireworks_midi.c +++ b/sound/firewire/fireworks/fireworks_midi.c @@ -22,6 +22,8 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err >= 0) { ++efw->substreams_counter; err = snd_efw_stream_start_duplex(efw); + if (err < 0) + --efw->substreams_counter; } mutex_unlock(&efw->mutex); if (err < 0) From 03a954aef70e10003b3f1cf7066ab7c955eb27f1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 14:20:08 +0900 Subject: [PATCH 615/626] ALSA: oxfw: fix wrong reference count for stream functionality at error path of rawmidi interface In IEC 61883-6, several types of sampling data can be multiplexed into payload of common isochronous packet (CIP). For typical audio and music units, PCM samples and MIDI messages are multiplexed into one packet streaming. ALSA oxfw driver allows applications of rawmidi interface to start packet streaming for transmission of MIDI messages. However at error path, the reference count of stream functionality is not operated correctly. This can brings a bug that packet streaming is not stopped when all referrers release the count. This commit fixes the bug. Fixes: 4f380d007052 ("ALSA: oxfw: configure packet format in pcm.hw_params callback") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-midi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/firewire/oxfw/oxfw-midi.c b/sound/firewire/oxfw/oxfw-midi.c index 9ba62778add2..92538ab06932 100644 --- a/sound/firewire/oxfw/oxfw-midi.c +++ b/sound/firewire/oxfw/oxfw-midi.c @@ -23,6 +23,8 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) if (err >= 0) { ++oxfw->substreams_count; err = snd_oxfw_stream_start_duplex(oxfw); + if (err < 0) + --oxfw->substreams_count; } mutex_unlock(&oxfw->mutex); From e79c3f0c006ec26d0de5ba9747f65b81c16f83f1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 14:20:09 +0900 Subject: [PATCH 616/626] ALSA: dice: fix wrong reference count for stream functionality at error path of rawmidi interface In IEC 61883-6, several types of sampling data can be multiplexed into payload of common isochronous packet (CIP). For typical audio and music units, PCM samples and MIDI messages are multiplexed into one packet streaming. ALSA dice driver allows applications of rawmidi interface to start packet streaming for transmission of MIDI messages. However at error path, the reference count of stream functionality is not operated correctly. This can brings a bug that packet streaming is not stopped when all referrers release the count. This commit fixes the bug. Fixes: 3cd2c2d780a2 ("ALSA: dice: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-midi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c index 436f0c3c0fbb..30a0b8200160 100644 --- a/sound/firewire/dice/dice-midi.c +++ b/sound/firewire/dice/dice-midi.c @@ -22,6 +22,8 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err >= 0) { ++dice->substreams_counter; err = snd_dice_stream_start_duplex(dice); + if (err < 0) + --dice->substreams_counter; } mutex_unlock(&dice->mutex); From 64582c56a9156ce88297a89a3b8ba03754e7149a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 14:20:10 +0900 Subject: [PATCH 617/626] ALSA: firewire-digi00x: fix wrong reference count for stream functionality at error path of rawmidi interface In IEC 61883-6, several types of sampling data can be multiplexed into payload of common isochronous packet (CIP). For typical audio and music units, PCM samples and MIDI messages are multiplexed into one packet streaming. ALSA firewire-digi00x driver allows applications of rawmidi interface to start packet streaming for transmission of MIDI messages. However at error path, the reference count of stream functionality is not operated correctly. This can brings a bug that packet streaming is not stopped when all referrers release the count. This commit fixes the bug. Fixes: ae8ffbb26512 ("ALSA: firewire-digi00x: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-midi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/firewire/digi00x/digi00x-midi.c b/sound/firewire/digi00x/digi00x-midi.c index ca06ad318ed6..0563701141b8 100644 --- a/sound/firewire/digi00x/digi00x-midi.c +++ b/sound/firewire/digi00x/digi00x-midi.c @@ -22,6 +22,8 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err >= 0) { ++dg00x->substreams_counter; err = snd_dg00x_stream_start_duplex(dg00x); + if (err < 0) + --dg00x->substreams_counter; } mutex_unlock(&dg00x->mutex); if (err < 0) From ba18ca2b8e18146228ff36b50f0c9a3f5c5bd1b5 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 14:20:11 +0900 Subject: [PATCH 618/626] firewire-motu: fix wrong reference count for stream functionality at error path of rawmidi interface In IEC 61883-6, several types of sampling data can be multiplexed into payload of common isochronous packet (CIP). For typical audio and music units, PCM samples and MIDI messages are multiplexed into one packet streaming. ALSA firewire-motu driver allows applications of rawmidi interface to start packet streaming for transmission of MIDI messages. However at error path, the reference count of stream functionality is not operated correctly. This can brings a bug that packet streaming is not stopped when all referrers release the count. This commit fixes the bug. Fixes: 8edc56ec8f14 ("ALSA: firewire-motu: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-midi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/firewire/motu/motu-midi.c b/sound/firewire/motu/motu-midi.c index 4520c0060b83..5c77e417c627 100644 --- a/sound/firewire/motu/motu-midi.c +++ b/sound/firewire/motu/motu-midi.c @@ -22,6 +22,8 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err >= 0) { ++motu->substreams_counter; err = snd_motu_stream_start_duplex(motu); + if (err < 0) + --motu->substreams_counter; } mutex_unlock(&motu->mutex); From d4bd30532688558a7de70f0c8edd2a7a25c3963f Mon Sep 17 00:00:00 2001 From: Nicola Lunghi Date: Sun, 7 Jul 2019 09:27:34 +0100 Subject: [PATCH 619/626] ALSA: usb-audio: fix Line6 Helix audio format rates Line6 Helix and HX stomp devices don't support retrieving the number of clock sample rate. Add a quirk to set it to 48Khz by default. [ fixed wrong variable initialization changes by tiwai ] Signed-off-by: Nicola Lunghi Signed-off-by: Takashi Iwai --- sound/usb/format.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/sound/usb/format.c b/sound/usb/format.c index 3ee7d6f853b7..c391ae03a07b 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -298,6 +298,33 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, return nr_rates; } +/* Line6 Helix series don't support the UAC2_CS_RANGE usb function + * call. Return a static table of known clock rates. + */ +static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip, + struct audioformat *fp) +{ + switch (chip->usb_id) { + case USB_ID(0x0E41, 0x4241): /* Line6 Helix */ + case USB_ID(0x0E41, 0x4242): /* Line6 Helix Rack */ + case USB_ID(0x0E41, 0x4244): /* Line6 Helix LT */ + case USB_ID(0x0E41, 0x4246): /* Line6 HX-Stomp */ + /* supported rates: 48Khz */ + kfree(fp->rate_table); + fp->rate_table = kmalloc(sizeof(int), GFP_KERNEL); + if (!fp->rate_table) + return -ENOMEM; + fp->nr_rates = 1; + fp->rate_min = 48000; + fp->rate_max = 48000; + fp->rates = SNDRV_PCM_RATE_48000; + fp->rate_table[0] = 48000; + return 0; + } + + return -ENODEV; +} + /* * parse the format descriptor and stores the possible sample rates * on the audioformat table (audio class v2 and v3). @@ -307,7 +334,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, { struct usb_device *dev = chip->dev; unsigned char tmp[2], *data; - int nr_triplets, data_size, ret = 0; + int nr_triplets, data_size, ret = 0, ret_l6; int clock = snd_usb_clock_find_source(chip, fp->protocol, fp->clock, false); @@ -326,9 +353,22 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, tmp, sizeof(tmp)); if (ret < 0) { - dev_err(&dev->dev, - "%s(): unable to retrieve number of sample rates (clock %d)\n", + /* line6 helix devices don't support UAC2_CS_CONTROL_SAM_FREQ call */ + ret_l6 = line6_parse_audio_format_rates_quirk(chip, fp); + if (ret_l6 == -ENODEV) { + /* no line6 device found continue showing the error */ + dev_err(&dev->dev, + "%s(): unable to retrieve number of sample rates (clock %d)\n", __func__, clock); + goto err; + } + if (ret_l6 == 0) { + dev_info(&dev->dev, + "%s(): unable to retrieve number of sample rates: set it to a predefined value (clock %d).\n", + __func__, clock); + return 0; + } + ret = ret_l6; goto err; } From 0ebf3ceb83648f9d149220bf0c6986ddce11361a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 21:07:53 +0900 Subject: [PATCH 620/626] ALSA: firewire-lib: fix invalid length of rx packet payload for tracepoint events Although CIP header is handled as context header, the length of isochronous packet includes two quadlets for its payload. In tracepoints event the value of payload_quadlets should includes the two quadlets. But at present it doesn't. This commit fixes the bug. Fixes: b18f0cfaf16b ("ALSA: firewire-lib: use 8 byte packet header for IT context to separate CIP header from CIP payload") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 87a46bd60496..427624009de9 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -490,8 +490,12 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, unsigned int data_blocks, unsigned int syt, unsigned int index) { + unsigned int payload_length; __be32 *cip_header; + payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; + params->payload_length = payload_length; + if (s->flags & CIP_DBC_IS_END_EVENT) { s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; @@ -501,6 +505,7 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, cip_header = (__be32 *)params->header; generate_cip_header(s, cip_header, syt); params->header_length = 2 * sizeof(__be32); + payload_length += params->header_length; } else { cip_header = NULL; } @@ -510,11 +515,8 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, (s->data_block_counter + data_blocks) & 0xff; } - params->payload_length = - data_blocks * sizeof(__be32) * s->data_block_quadlets; - - trace_amdtp_packet(s, cycle, cip_header, params->payload_length, - data_blocks, index); + trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, + index); } static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, From 7fbf909668d69d7ab4428f6f55cb53fe4451b9b1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 21:07:54 +0900 Subject: [PATCH 621/626] ALSA: firewire-lib/fireface: fix initial value of data block counter for IR context with CIP_NO_HEADER For IR context, ALSA IEC 61883-1/6 engine uses initial value of data block counter as UINT_MAX, to detect first isochronous packet in the middle of packet streaming. At present, when CIP_NO_HEADER is used (i.e. for ALSA fireface driver), the initial value is used for tracepoints event. 0x00 should be for the event when the initial value is UINT_MAX because isochronous packets with CIP_NO_HEADER option has no field for data block count. This commit fixes the bug. Fixes: 76864868dbab ("ALSA: firewire-lib: cache next data_block_counter after probing tracepoints event for IR context") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 427624009de9..b60cf25ee5a8 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -646,8 +646,12 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, err = 0; *data_blocks = *payload_length / sizeof(__be32) / s->data_block_quadlets; - *dbc = s->data_block_counter; *syt = 0; + + if (s->data_block_counter != UINT_MAX) + *dbc = s->data_block_counter; + else + *dbc = 0; } if (err >= 0 && s->flags & CIP_DBC_IS_END_EVENT) From 4ece7f6fd830d71bbb185434bf081b1f47701a67 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 21:07:55 +0900 Subject: [PATCH 622/626] ALSA: firewire-lib: fix initial value of data block count for IR context without CIP_DBC_IS_END_EVENT For IR context, ALSA IEC 61883-1/6 engine uses initial value of data block counter as UINT_MAX, to detect first isochronous packet in the middle of packet streaming. At present, when CIP_DBC_IS_END_EVENT is not used (i.e. for drivers except for ALSA fireworks driver), the initial value is used as is for tracepoints event. However, the engine can detect the value of dbc field in the payload of first isochronous packet and the value should be assigned to the event. This commit fixes the bug. Fixes: 76864868dbab ("ALSA: firewire-lib: cache next data_block_counter after probing tracepoints event for IR context") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index b60cf25ee5a8..3d410057eaa4 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -654,8 +654,10 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, *dbc = 0; } - if (err >= 0 && s->flags & CIP_DBC_IS_END_EVENT) - s->data_block_counter = *dbc; + if (err < 0) + return err; + + s->data_block_counter = *dbc; trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, index); From 213fa98981588887c1a2ed817e6a48e2428e97a1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 21:07:56 +0900 Subject: [PATCH 623/626] ALSA: firewire-lib: fix different data block counter between probed event and transferred isochronous packet For IT context, tracepoints event is probed after calculating next data block counter. This brings difference of data block counter between the probed event and actual isochronous packet. This commit fixes it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 3d410057eaa4..9259375caac4 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -510,13 +510,13 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, cip_header = NULL; } + trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, + index); + if (!(s->flags & CIP_DBC_IS_END_EVENT)) { s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; } - - trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, - index); } static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, From b8b0e24c226e4434821f437070935218fdd39741 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 21:07:57 +0900 Subject: [PATCH 624/626] ALSA: firewire-lib: code refactoring for error path of parser for CIP header When a parser for CIP header returns -EAGAIN, no extra care is needed to probe tracepoints event. This commit adds code refactoring for the error path. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 9259375caac4..0b9e643187e2 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -635,12 +635,8 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, cip_header = ctx_header + 2; err = check_cip_header(s, cip_header, *payload_length, data_blocks, dbc, syt); - if (err < 0) { - if (err != -EAGAIN) - return err; - - *data_blocks = 0; - } + if (err < 0) + return err; } else { cip_header = NULL; err = 0; @@ -654,9 +650,6 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, *dbc = 0; } - if (err < 0) - return err; - s->data_block_counter = *dbc; trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, From 02394af3e00df73c3674de0783d3a31c8162c840 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 21:07:58 +0900 Subject: [PATCH 625/626] ALSA: firewire-lib: code refactoring for post operation to data block counter As a result of former commits, post operation to data block count for cases without CIP_DBC_IS_END_EVENT can be done just with data_block_counter member of amdtp_stream structure. This commit adds code refactoring to obsolete local variable for data block counter. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 0b9e643187e2..5e0346e272aa 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -616,9 +616,10 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, const __be32 *ctx_header, unsigned int *payload_length, - unsigned int *data_blocks, unsigned int *dbc, - unsigned int *syt, unsigned int index) + unsigned int *data_blocks, unsigned int *syt, + unsigned int index) { + unsigned int dbc; const __be32 *cip_header; int err; @@ -634,7 +635,7 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, if (!(s->flags & CIP_NO_HEADER)) { cip_header = ctx_header + 2; err = check_cip_header(s, cip_header, *payload_length, - data_blocks, dbc, syt); + data_blocks, &dbc, syt); if (err < 0) return err; } else { @@ -645,12 +646,12 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, *syt = 0; if (s->data_block_counter != UINT_MAX) - *dbc = s->data_block_counter; + dbc = s->data_block_counter; else - *dbc = 0; + dbc = 0; } - s->data_block_counter = *dbc; + s->data_block_counter = dbc; trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, index); @@ -758,7 +759,6 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, u32 cycle; unsigned int payload_length; unsigned int data_blocks; - unsigned int dbc; unsigned int syt; __be32 *buffer; unsigned int pcm_frames = 0; @@ -768,7 +768,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, cycle = compute_cycle_count(ctx_header[1]); err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, - &data_blocks, &dbc, &syt, i); + &data_blocks, &syt, i); if (err < 0 && err != -EAGAIN) break; @@ -778,8 +778,8 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, data_blocks, &syt); if (!(s->flags & CIP_DBC_IS_END_EVENT)) { - s->data_block_counter = - (dbc + data_blocks) & 0xff; + s->data_block_counter += data_blocks; + s->data_block_counter &= 0xff; } } From 0dcb4efb1095d0a1f5f681c2b94e98b009cc5d77 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 7 Jul 2019 21:07:59 +0900 Subject: [PATCH 626/626] ALSA: firewire-lib: code refactoring for local variables It's better to use int type for loop index. For consistency, the name of local variable for the number of data block should be plural. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 5e0346e272aa..4d71d74707cf 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -700,7 +700,8 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, { struct amdtp_stream *s = private_data; const __be32 *ctx_header = header; - unsigned int i, packets = header_length / sizeof(*ctx_header); + unsigned int packets = header_length / sizeof(*ctx_header); + int i; if (s->packet_index < 0) return; @@ -708,7 +709,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; ++i) { u32 cycle; unsigned int syt; - unsigned int data_block; + unsigned int data_blocks; __be32 *buffer; unsigned int pcm_frames; struct { @@ -719,12 +720,13 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, cycle = compute_it_cycle(*ctx_header); syt = calculate_syt(s, cycle); - data_block = calculate_data_blocks(s, syt); + data_blocks = calculate_data_blocks(s, syt); buffer = s->buffer.packets[s->packet_index].buffer; - pcm_frames = s->process_data_blocks(s, buffer, data_block, &syt); + pcm_frames = s->process_data_blocks(s, buffer, data_blocks, + &syt); - build_it_pkt_header(s, cycle, &template.params, data_block, syt, - i); + build_it_pkt_header(s, cycle, &template.params, data_blocks, + syt, i); if (queue_out_packet(s, &template.params) < 0) { cancel_stream(s);