diff options
Diffstat (limited to 'sound/soc/fsl')
30 files changed, 834 insertions, 124 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 33b67db8794e..725c530a3636 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -172,6 +172,15 @@ config SND_MPC52xx_DMA config SND_SOC_POWERPC_DMA tristate +config SND_SOC_POWERPC_QMC_AUDIO + tristate "QMC ALSA SoC support" + depends on CPM_QMC + help + ALSA SoC Audio support using the Freescale QUICC Multichannel + Controller (QMC). + Say Y or M if you want to add support for SoC audio using Freescale + QMC. + comment "SoC Audio support for Freescale PPC boards:" config SND_SOC_MPC8610_HPCD diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index b54beb1a66fa..8db7e97d0bd5 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -28,6 +28,7 @@ snd-soc-fsl-easrc-objs := fsl_easrc.o snd-soc-fsl-xcvr-objs := fsl_xcvr.o snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o snd-soc-fsl-rpmsg-objs := fsl_rpmsg.o +snd-soc-fsl-qmc-audio-objs := fsl_qmc_audio.o obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o +obj-$(CONFIG_SND_SOC_POWERPC_QMC_AUDIO) += snd-soc-fsl-qmc-audio.o # MPC5200 Platform Support obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 9af4c4a35eb1..e65a85feba78 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -205,11 +205,9 @@ err: return ret; } -static int eukrea_tlv320_remove(struct platform_device *pdev) +static void eukrea_tlv320_remove(struct platform_device *pdev) { snd_soc_unregister_card(&eukrea_tlv320); - - return 0; } static const struct of_device_id imx_tlv320_dt_ids[] = { @@ -224,7 +222,7 @@ static struct platform_driver eukrea_tlv320_driver = { .of_match_table = imx_tlv320_dt_ids, }, .probe = eukrea_tlv320_probe, - .remove = eukrea_tlv320_remove, + .remove_new = eukrea_tlv320_remove, }; module_platform_driver(eukrea_tlv320_driver); diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index cdfca9fd1eb0..40870668ee24 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -28,6 +28,8 @@ #include "../codecs/wm8994.h" #include "../codecs/tlv320aic31xx.h" +#define DRIVER_NAME "fsl-asoc-card" + #define CS427x_SYSCLK_MCLK 0 #define RX 0 @@ -607,6 +609,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dapm_routes = audio_map; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); + priv->card.driver_name = DRIVER_NAME; /* Diversify the card configurations */ if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { codec_dai_name = "cs42888"; @@ -855,7 +858,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); if (ret) { - dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed: %d\n", ret); + dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n"); goto asrc_fail; } @@ -915,7 +918,7 @@ MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids); static struct platform_driver fsl_asoc_card_driver = { .probe = fsl_asoc_card_probe, .driver = { - .name = "fsl-asoc-card", + .name = DRIVER_NAME, .pm = &snd_soc_pm_ops, .of_match_table = fsl_asoc_card_dt_ids, }, @@ -924,5 +927,5 @@ module_platform_driver(fsl_asoc_card_driver); MODULE_DESCRIPTION("Freescale Generic ASoC Sound Card driver with ASRC"); MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>"); -MODULE_ALIAS("platform:fsl-asoc-card"); +MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL"); diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index e16e7b3fa96c..adb8a59de2bd 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1252,13 +1252,11 @@ err_pm_disable: return ret; } -static int fsl_asrc_remove(struct platform_device *pdev) +static void fsl_asrc_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) fsl_asrc_runtime_suspend(&pdev->dev); - - return 0; } static int fsl_asrc_runtime_resume(struct device *dev) @@ -1394,7 +1392,7 @@ MODULE_DEVICE_TABLE(of, fsl_asrc_ids); static struct platform_driver fsl_asrc_driver = { .probe = fsl_asrc_probe, - .remove = fsl_asrc_remove, + .remove_new = fsl_asrc_remove, .driver = { .name = "fsl-asrc", .of_match_table = fsl_asrc_ids, diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c index 1e421d9a03fb..46b0c5dcc4a5 100644 --- a/sound/soc/fsl/fsl_aud2htx.c +++ b/sound/soc/fsl/fsl_aud2htx.c @@ -257,11 +257,9 @@ static int fsl_aud2htx_probe(struct platform_device *pdev) return ret; } -static int fsl_aud2htx_remove(struct platform_device *pdev) +static void fsl_aud2htx_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused fsl_aud2htx_runtime_suspend(struct device *dev) @@ -300,7 +298,7 @@ static const struct dev_pm_ops fsl_aud2htx_pm_ops = { static struct platform_driver fsl_aud2htx_driver = { .probe = fsl_aud2htx_probe, - .remove = fsl_aud2htx_remove, + .remove_new = fsl_aud2htx_remove, .driver = { .name = "fsl-aud2htx", .pm = &fsl_aud2htx_pm_ops, diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 672148dd4b23..0ab2c1962117 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -506,7 +506,7 @@ err_disable_pm: return ret; } -static int fsl_audmix_remove(struct platform_device *pdev) +static void fsl_audmix_remove(struct platform_device *pdev) { struct fsl_audmix *priv = dev_get_drvdata(&pdev->dev); @@ -514,8 +514,6 @@ static int fsl_audmix_remove(struct platform_device *pdev) if (priv->pdev) platform_device_unregister(priv->pdev); - - return 0; } #ifdef CONFIG_PM @@ -558,7 +556,7 @@ static const struct dev_pm_ops fsl_audmix_pm = { static struct platform_driver fsl_audmix_driver = { .probe = fsl_audmix_probe, - .remove = fsl_audmix_remove, + .remove_new = fsl_audmix_remove, .driver = { .name = "fsl-audmix", .of_match_table = fsl_audmix_ids, diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 808fb61a7a0f..963f9774c883 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -890,15 +890,13 @@ static int fsl_soc_dma_probe(struct platform_device *pdev) return 0; } -static int fsl_soc_dma_remove(struct platform_device *pdev) +static void fsl_soc_dma_remove(struct platform_device *pdev) { struct dma_object *dma = dev_get_drvdata(&pdev->dev); iounmap(dma->channel); irq_dispose_mapping(dma->irq); kfree(dma); - - return 0; } static const struct of_device_id fsl_soc_dma_ids[] = { @@ -913,7 +911,7 @@ static struct platform_driver fsl_soc_dma_driver = { .of_match_table = fsl_soc_dma_ids, }, .probe = fsl_soc_dma_probe, - .remove = fsl_soc_dma_remove, + .remove_new = fsl_soc_dma_remove, }; module_platform_driver(fsl_soc_dma_driver); diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 3153d19136b2..670cbdb361b6 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1979,11 +1979,9 @@ static int fsl_easrc_probe(struct platform_device *pdev) return 0; } -static int fsl_easrc_remove(struct platform_device *pdev) +static void fsl_easrc_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static __maybe_unused int fsl_easrc_runtime_suspend(struct device *dev) @@ -2093,7 +2091,7 @@ static const struct dev_pm_ops fsl_easrc_pm_ops = { static struct platform_driver fsl_easrc_driver = { .probe = fsl_easrc_probe, - .remove = fsl_easrc_remove, + .remove_new = fsl_easrc_remove, .driver = { .name = "fsl-easrc", .pm = &fsl_easrc_pm_ops, diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 17fefd27ec90..936f0cd4b06d 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -1101,7 +1101,7 @@ err_pm_disable: return ret; } -static int fsl_esai_remove(struct platform_device *pdev) +static void fsl_esai_remove(struct platform_device *pdev) { struct fsl_esai *esai_priv = platform_get_drvdata(pdev); @@ -1110,8 +1110,6 @@ static int fsl_esai_remove(struct platform_device *pdev) fsl_esai_runtime_suspend(&pdev->dev); cancel_work_sync(&esai_priv->work); - - return 0; } static const struct of_device_id fsl_esai_dt_ids[] = { @@ -1200,7 +1198,7 @@ static const struct dev_pm_ops fsl_esai_pm_ops = { static struct platform_driver fsl_esai_driver = { .probe = fsl_esai_probe, - .remove = fsl_esai_remove, + .remove_new = fsl_esai_remove, .driver = { .name = "fsl-esai-dai", .pm = &fsl_esai_pm_ops, diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 4922e6795b73..49ae7f6267d3 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -210,10 +210,10 @@ static int fsl_mqs_probe(struct platform_device *pdev) } mqs_priv->regmap = syscon_node_to_regmap(gpr_np); + of_node_put(gpr_np); if (IS_ERR(mqs_priv->regmap)) { dev_err(&pdev->dev, "failed to get gpr regmap\n"); - ret = PTR_ERR(mqs_priv->regmap); - goto err_free_gpr_np; + return PTR_ERR(mqs_priv->regmap); } } else { regs = devm_platform_ioremap_resource(pdev, 0); @@ -242,8 +242,7 @@ static int fsl_mqs_probe(struct platform_device *pdev) if (IS_ERR(mqs_priv->mclk)) { dev_err(&pdev->dev, "failed to get the clock: %ld\n", PTR_ERR(mqs_priv->mclk)); - ret = PTR_ERR(mqs_priv->mclk); - goto err_free_gpr_np; + return PTR_ERR(mqs_priv->mclk); } dev_set_drvdata(&pdev->dev, mqs_priv); @@ -252,19 +251,14 @@ static int fsl_mqs_probe(struct platform_device *pdev) ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_fsl_mqs, &fsl_mqs_dai, 1); if (ret) - goto err_free_gpr_np; - return 0; - -err_free_gpr_np: - of_node_put(gpr_np); + return ret; - return ret; + return 0; } -static int fsl_mqs_remove(struct platform_device *pdev) +static void fsl_mqs_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } #ifdef CONFIG_PM @@ -360,7 +354,7 @@ MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids); static struct platform_driver fsl_mqs_driver = { .probe = fsl_mqs_probe, - .remove = fsl_mqs_remove, + .remove_new = fsl_mqs_remove, .driver = { .name = "fsl-mqs", .of_match_table = fsl_mqs_dt_ids, diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c new file mode 100644 index 000000000000..7cbb8e4758cc --- /dev/null +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -0,0 +1,735 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ALSA SoC using the QUICC Multichannel Controller (QMC) + * + * Copyright 2022 CS GROUP France + * + * Author: Herve Codina <herve.codina@bootlin.com> + */ + +#include <linux/dma-mapping.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <soc/fsl/qe/qmc.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +struct qmc_dai { + char *name; + int id; + struct device *dev; + struct qmc_chan *qmc_chan; + unsigned int nb_tx_ts; + unsigned int nb_rx_ts; +}; + +struct qmc_audio { + struct device *dev; + unsigned int num_dais; + struct qmc_dai *dais; + struct snd_soc_dai_driver *dai_drivers; +}; + +struct qmc_dai_prtd { + struct qmc_dai *qmc_dai; + dma_addr_t dma_buffer_start; + dma_addr_t period_ptr_submitted; + dma_addr_t period_ptr_ended; + dma_addr_t dma_buffer_end; + size_t period_size; + struct snd_pcm_substream *substream; +}; + +static int qmc_audio_pcm_construct(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + int ret; + + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, + 64*1024, 64*1024); + return 0; +} + +static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + prtd->dma_buffer_start = runtime->dma_addr; + prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params); + prtd->period_size = params_period_bytes(params); + prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->period_ptr_ended = prtd->dma_buffer_start; + prtd->substream = substream; + + return 0; +} + +static void qmc_audio_pcm_write_complete(void *context) +{ + struct qmc_dai_prtd *prtd = context; + int ret; + + prtd->period_ptr_ended += prtd->period_size; + if (prtd->period_ptr_ended >= prtd->dma_buffer_end) + prtd->period_ptr_ended = prtd->dma_buffer_start; + + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", + ret); + } + + snd_pcm_period_elapsed(prtd->substream); +} + +static void qmc_audio_pcm_read_complete(void *context, size_t length) +{ + struct qmc_dai_prtd *prtd = context; + int ret; + + if (length != prtd->period_size) { + dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", + length, prtd->period_size); + } + + prtd->period_ptr_ended += prtd->period_size; + if (prtd->period_ptr_ended >= prtd->dma_buffer_end) + prtd->period_ptr_ended = prtd->dma_buffer_start; + + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", + ret); + } + + snd_pcm_period_elapsed(prtd->substream); +} + +static int qmc_audio_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + int ret; + + if (!prtd->qmc_dai) { + dev_err(component->dev, "qmc_dai is not set\n"); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* Submit first chunk ... */ + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + + /* ... prepare next one ... */ + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + /* ... and send it */ + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + } else { + /* Submit first chunk ... */ + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(component->dev, "read_submit failed %d\n", + ret); + return ret; + } + + /* ... prepare next one ... */ + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + /* ... and send it */ + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + } + break; + + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + + default: + return -EINVAL; + } + + return 0; +} + +static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + return bytes_to_frames(substream->runtime, + prtd->period_ptr_ended - prtd->dma_buffer_start); +} + +static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component, + const struct of_phandle_args *args, + const char **dai_name) +{ + struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev); + struct snd_soc_dai_driver *dai_driver; + int id = args->args[0]; + int i; + + for (i = 0; i < qmc_audio->num_dais; i++) { + dai_driver = qmc_audio->dai_drivers + i; + if (dai_driver->id == id) { + *dai_name = dai_driver->name; + return 0; + } + } + + return -EINVAL; +} + +static const struct snd_pcm_hardware qmc_audio_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE, + .period_bytes_min = 32, + .period_bytes_max = 64*1024, + .periods_min = 2, + .periods_max = 2*1024, + .buffer_bytes_max = 64*1024, +}; + +static int qmc_audio_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct qmc_dai_prtd *prtd; + int ret; + + snd_soc_set_runtime_hwparams(substream, &qmc_audio_pcm_hardware); + + /* ensure that buffer size is a multiple of period size */ + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (prtd == NULL) + return -ENOMEM; + + runtime->private_data = prtd; + + return 0; +} + +static int qmc_audio_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + kfree(prtd); + return 0; +} + +static const struct snd_soc_component_driver qmc_audio_soc_platform = { + .open = qmc_audio_pcm_open, + .close = qmc_audio_pcm_close, + .hw_params = qmc_audio_pcm_hw_params, + .trigger = qmc_audio_pcm_trigger, + .pointer = qmc_audio_pcm_pointer, + .pcm_construct = qmc_audio_pcm_construct, + .of_xlate_dai_name = qmc_audio_of_xlate_dai_name, +}; + +static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai) +{ + struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); + + return dai->driver - qmc_audio->dai_drivers; +} + +static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai) +{ + struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); + unsigned int index; + + index = qmc_dai_get_index(dai); + if (index > qmc_audio->num_dais) + return NULL; + + return qmc_audio->dais + index; +} + +/* + * The constraints for format/channel is to match with the number of 8bit + * time-slots available. + */ +static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai, + struct snd_pcm_hw_params *params, + unsigned int nb_ts) +{ + struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + snd_pcm_format_t format = params_format(params); + struct snd_interval ch = {0}; + + switch (snd_pcm_format_physical_width(format)) { + case 8: + ch.max = nb_ts; + break; + case 16: + ch.max = nb_ts/2; + break; + case 32: + ch.max = nb_ts/4; + break; + case 64: + ch.max = nb_ts/8; + break; + default: + dev_err(qmc_dai->dev, "format physical width %u not supported\n", + snd_pcm_format_physical_width(format)); + return -EINVAL; + } + + ch.min = ch.max ? 1 : 0; + + return snd_interval_refine(c, &ch); +} + +static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts); +} + +static int qmc_dai_hw_rule_capture_channels_by_format( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts); +} + +static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai, + struct snd_pcm_hw_params *params, + unsigned int nb_ts) +{ + struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + unsigned int channels = params_channels(params); + unsigned int slot_width; + struct snd_mask f_new; + unsigned int i; + + if (!channels || channels > nb_ts) { + dev_err(qmc_dai->dev, "channels %u not supported\n", + nb_ts); + return -EINVAL; + } + + slot_width = (nb_ts / channels) * 8; + + snd_mask_none(&f_new); + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + if (snd_mask_test(f_old, i)) { + if (snd_pcm_format_physical_width(i) <= slot_width) + snd_mask_set(&f_new, i); + } + } + + return snd_mask_refine(f_old, &f_new); +} + +static int qmc_dai_hw_rule_playback_format_by_channels( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts); +} + +static int qmc_dai_hw_rule_capture_format_by_channels( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts); +} + +static int qmc_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + snd_pcm_hw_rule_func_t hw_rule_channels_by_format; + snd_pcm_hw_rule_func_t hw_rule_format_by_channels; + struct qmc_dai *qmc_dai; + unsigned int frame_bits; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + prtd->qmc_dai = qmc_dai; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format; + hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels; + frame_bits = qmc_dai->nb_rx_ts * 8; + } else { + hw_rule_channels_by_format = qmc_dai_hw_rule_playback_channels_by_format; + hw_rule_format_by_channels = qmc_dai_hw_rule_playback_format_by_channels; + frame_bits = qmc_dai->nb_tx_ts * 8; + } + + ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_channels_by_format, qmc_dai, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (ret) { + dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_format_by_channels, qmc_dai, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (ret) { + dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_FRAME_BITS, + frame_bits); + if (ret < 0) { + dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); + return ret; + } + + return 0; +} + +static int qmc_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct qmc_chan_param chan_param = {0}; + struct qmc_dai *qmc_dai; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + chan_param.mode = QMC_TRANSPARENT; + chan_param.transp.max_rx_buf_size = params_period_bytes(params); + ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param); + if (ret) { + dev_err(dai->dev, "set param failed %d\n", + ret); + return ret; + } + } + + return 0; +} + +static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct qmc_dai *qmc_dai; + int direction; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + QMC_CHAN_WRITE : QMC_CHAN_READ; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = qmc_chan_start(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + case SNDRV_PCM_TRIGGER_STOP: + ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + ret = qmc_chan_reset(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops qmc_dai_ops = { + .startup = qmc_dai_startup, + .trigger = qmc_dai_trigger, + .hw_params = qmc_dai_hw_params, +}; + +static u64 qmc_audio_formats(u8 nb_ts) +{ + u64 formats; + unsigned int chan_width; + unsigned int format_width; + int i; + + if (!nb_ts) + return 0; + + formats = 0; + chan_width = nb_ts * 8; + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + /* + * Support format other than little-endian (ie big-endian or + * without endianness such as 8bit formats) + */ + if (snd_pcm_format_little_endian(i) == 1) + continue; + + /* Support physical width multiple of 8bit */ + format_width = snd_pcm_format_physical_width(i); + if (format_width == 0 || format_width % 8) + continue; + + /* + * And support physical width that can fit N times in the + * channel + */ + if (format_width > chan_width || chan_width % format_width) + continue; + + formats |= (1ULL << i); + } + return formats; +} + +static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np, + struct qmc_dai *qmc_dai, struct snd_soc_dai_driver *qmc_soc_dai_driver) +{ + struct qmc_chan_info info; + u32 val; + int ret; + + qmc_dai->dev = qmc_audio->dev; + + ret = of_property_read_u32(np, "reg", &val); + if (ret) { + dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np); + return ret; + } + qmc_dai->id = val; + + qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d", + np->parent->name, qmc_dai->id); + + qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, + "fsl,qmc-chan"); + if (IS_ERR(qmc_dai->qmc_chan)) { + ret = PTR_ERR(qmc_dai->qmc_chan); + return dev_err_probe(qmc_audio->dev, ret, + "dai %d get QMC channel failed\n", qmc_dai->id); + } + + qmc_soc_dai_driver->id = qmc_dai->id; + qmc_soc_dai_driver->name = qmc_dai->name; + + ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info); + if (ret) { + dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", + qmc_dai->id, ret); + return ret; + } + dev_info(qmc_audio->dev, "dai %d QMC channel mode %d, nb_tx_ts %u, nb_rx_ts %u\n", + qmc_dai->id, info.mode, info.nb_tx_ts, info.nb_rx_ts); + + if (info.mode != QMC_TRANSPARENT) { + dev_err(qmc_audio->dev, "dai %d QMC chan mode %d is not QMC_TRANSPARENT\n", + qmc_dai->id, info.mode); + return -EINVAL; + } + qmc_dai->nb_tx_ts = info.nb_tx_ts; + qmc_dai->nb_rx_ts = info.nb_rx_ts; + + qmc_soc_dai_driver->playback.channels_min = 0; + qmc_soc_dai_driver->playback.channels_max = 0; + if (qmc_dai->nb_tx_ts) { + qmc_soc_dai_driver->playback.channels_min = 1; + qmc_soc_dai_driver->playback.channels_max = qmc_dai->nb_tx_ts; + } + qmc_soc_dai_driver->playback.formats = qmc_audio_formats(qmc_dai->nb_tx_ts); + + qmc_soc_dai_driver->capture.channels_min = 0; + qmc_soc_dai_driver->capture.channels_max = 0; + if (qmc_dai->nb_rx_ts) { + qmc_soc_dai_driver->capture.channels_min = 1; + qmc_soc_dai_driver->capture.channels_max = qmc_dai->nb_rx_ts; + } + qmc_soc_dai_driver->capture.formats = qmc_audio_formats(qmc_dai->nb_rx_ts); + + qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(info.tx_fs_rate); + qmc_soc_dai_driver->playback.rate_min = info.tx_fs_rate; + qmc_soc_dai_driver->playback.rate_max = info.tx_fs_rate; + qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(info.rx_fs_rate); + qmc_soc_dai_driver->capture.rate_min = info.rx_fs_rate; + qmc_soc_dai_driver->capture.rate_max = info.rx_fs_rate; + + qmc_soc_dai_driver->ops = &qmc_dai_ops; + + return 0; +} + +static int qmc_audio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct qmc_audio *qmc_audio; + struct device_node *child; + unsigned int i; + int ret; + + qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL); + if (!qmc_audio) + return -ENOMEM; + + qmc_audio->dev = &pdev->dev; + + qmc_audio->num_dais = of_get_available_child_count(np); + if (qmc_audio->num_dais) { + qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, + sizeof(*qmc_audio->dais), + GFP_KERNEL); + if (!qmc_audio->dais) + return -ENOMEM; + + qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, + sizeof(*qmc_audio->dai_drivers), + GFP_KERNEL); + if (!qmc_audio->dai_drivers) + return -ENOMEM; + } + + i = 0; + for_each_available_child_of_node(np, child) { + ret = qmc_audio_dai_parse(qmc_audio, child, + qmc_audio->dais + i, + qmc_audio->dai_drivers + i); + if (ret) { + of_node_put(child); + return ret; + } + i++; + } + + + platform_set_drvdata(pdev, qmc_audio); + + ret = devm_snd_soc_register_component(qmc_audio->dev, + &qmc_audio_soc_platform, + qmc_audio->dai_drivers, + qmc_audio->num_dais); + if (ret) + return ret; + + return 0; +} + +static const struct of_device_id qmc_audio_id_table[] = { + { .compatible = "fsl,qmc-audio" }, + {} /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, qmc_audio_id_table); + +static struct platform_driver qmc_audio_driver = { + .driver = { + .name = "fsl-qmc-audio", + .of_match_table = of_match_ptr(qmc_audio_id_table), + }, + .probe = qmc_audio_probe, +}; +module_platform_driver(qmc_audio_driver); + +MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>"); +MODULE_DESCRIPTION("CPM/QE QMC audio driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 46c7868a2653..15b48b5ea856 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -247,14 +247,12 @@ static int fsl_rpmsg_probe(struct platform_device *pdev) return 0; } -static int fsl_rpmsg_remove(struct platform_device *pdev) +static void fsl_rpmsg_remove(struct platform_device *pdev) { struct fsl_rpmsg *rpmsg = platform_get_drvdata(pdev); if (rpmsg->card_pdev) platform_device_unregister(rpmsg->card_pdev); - - return 0; } #ifdef CONFIG_PM @@ -302,7 +300,7 @@ static const struct dev_pm_ops fsl_rpmsg_pm_ops = { static struct platform_driver fsl_rpmsg_driver = { .probe = fsl_rpmsg_probe, - .remove = fsl_rpmsg_remove, + .remove_new = fsl_rpmsg_remove, .driver = { .name = "fsl_rpmsg", .pm = &fsl_rpmsg_pm_ops, diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 1b197478b3d9..07d13dca852e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1380,18 +1380,18 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->cpu_dai_drv.symmetric_channels = 1; sai->cpu_dai_drv.symmetric_sample_bits = 1; - if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) && - of_find_property(np, "fsl,sai-asynchronous", NULL)) { + if (of_property_read_bool(np, "fsl,sai-synchronous-rx") && + of_property_read_bool(np, "fsl,sai-asynchronous")) { /* error out if both synchronous and asynchronous are present */ dev_err(dev, "invalid binding for synchronous mode\n"); return -EINVAL; } - if (of_find_property(np, "fsl,sai-synchronous-rx", NULL)) { + if (of_property_read_bool(np, "fsl,sai-synchronous-rx")) { /* Sync Rx with Tx */ sai->synchronous[RX] = false; sai->synchronous[TX] = true; - } else if (of_find_property(np, "fsl,sai-asynchronous", NULL)) { + } else if (of_property_read_bool(np, "fsl,sai-asynchronous")) { /* Discard all settings for asynchronous mode */ sai->synchronous[RX] = false; sai->synchronous[TX] = false; @@ -1400,7 +1400,7 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->cpu_dai_drv.symmetric_sample_bits = 0; } - if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && + if (of_property_read_bool(np, "fsl,sai-mclk-direction-output") && of_device_is_compatible(np, "fsl,imx6ul-sai")) { gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr"); if (IS_ERR(gpr)) { @@ -1443,7 +1443,7 @@ static int fsl_sai_probe(struct platform_device *pdev) dev_warn(dev, "Error reading SAI version: %d\n", ret); /* Select MCLK direction */ - if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && + if (of_property_read_bool(np, "fsl,sai-mclk-direction-output") && sai->soc_data->max_register >= FSL_SAI_MCTL) { regmap_update_bits(sai->regmap, FSL_SAI_MCTL, FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN); @@ -1489,13 +1489,11 @@ err_pm_disable: return ret; } -static int fsl_sai_remove(struct platform_device *pdev) +static void fsl_sai_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) fsl_sai_runtime_suspend(&pdev->dev); - - return 0; } static const struct fsl_sai_soc_data fsl_sai_vf610_data = { @@ -1696,7 +1694,7 @@ static const struct dev_pm_ops fsl_sai_pm_ops = { static struct platform_driver fsl_sai_driver = { .probe = fsl_sai_probe, - .remove = fsl_sai_remove, + .remove_new = fsl_sai_remove, .driver = { .name = "fsl-sai", .pm = &fsl_sai_pm_ops, diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 275aba8e0c46..015c3708aa04 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1659,11 +1659,9 @@ err_pm_disable: return ret; } -static int fsl_spdif_remove(struct platform_device *pdev) +static void fsl_spdif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM @@ -1765,7 +1763,7 @@ static struct platform_driver fsl_spdif_driver = { .pm = &fsl_spdif_pm, }, .probe = fsl_spdif_probe, - .remove = fsl_spdif_remove, + .remove_new = fsl_spdif_remove, }; module_platform_driver(fsl_spdif_driver); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 46a53551b955..53ed3701b0b0 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1447,7 +1447,7 @@ static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi) return -EINVAL; } strcpy(ssi->card_name, "ac97-codec"); - } else if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { + } else if (!of_property_read_bool(np, "fsl,ssi-asynchronous")) { /* * In synchronous mode, STCK and STFS ports are used by RX * as well. So the software should limit the sample rates, @@ -1671,7 +1671,7 @@ error_ac97_ops: return ret; } -static int fsl_ssi_remove(struct platform_device *pdev) +static void fsl_ssi_remove(struct platform_device *pdev) { struct fsl_ssi *ssi = dev_get_drvdata(&pdev->dev); @@ -1690,8 +1690,6 @@ static int fsl_ssi_remove(struct platform_device *pdev) snd_soc_set_ac97_ops(NULL); mutex_destroy(&ssi->ac97_reg_lock); } - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1737,7 +1735,7 @@ static struct platform_driver fsl_ssi_driver = { .pm = &fsl_ssi_pm, }, .probe = fsl_ssi_probe, - .remove = fsl_ssi_remove, + .remove_new = fsl_ssi_remove, }; module_platform_driver(fsl_ssi_driver); diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 2a78243df752..318fe77683f5 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1339,10 +1339,9 @@ static int fsl_xcvr_probe(struct platform_device *pdev) return ret; } -static int fsl_xcvr_remove(struct platform_device *pdev) +static void fsl_xcvr_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static __maybe_unused int fsl_xcvr_runtime_suspend(struct device *dev) @@ -1478,7 +1477,7 @@ static struct platform_driver fsl_xcvr_driver = { .pm = &fsl_xcvr_pm_ops, .of_match_table = fsl_xcvr_dt_ids, }, - .remove = fsl_xcvr_remove, + .remove_new = fsl_xcvr_remove, }; module_platform_driver(fsl_xcvr_driver); diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 1292a845c424..b2c5aca92c6b 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_kcalloc(&pdev->dev, 6, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec x 2 */ + dlc = devm_kcalloc(&pdev->dev, 4, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -238,9 +238,13 @@ 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]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + priv->dai[i].cpus = + priv->dai[i].platforms = &dlc[0]; + priv->dai[i].codecs = &dlc[1]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; @@ -252,7 +256,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); @@ -267,20 +270,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; diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 582f1e2431ee..be003a117b39 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -315,12 +315,10 @@ static int imx_audmux_probe(struct platform_device *pdev) return 0; } -static int imx_audmux_remove(struct platform_device *pdev) +static void imx_audmux_remove(struct platform_device *pdev) { if (audmux_type == IMX31_AUDMUX) audmux_debugfs_remove(); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -359,7 +357,7 @@ static const struct dev_pm_ops imx_audmux_pm = { static struct platform_driver imx_audmux_driver = { .probe = imx_audmux_probe, - .remove = imx_audmux_remove, + .remove_new = imx_audmux_remove, .driver = { .name = DRIVER_NAME, .pm = &imx_audmux_pm, diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 3f128ced4180..64a4d7e9db60 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -563,7 +563,7 @@ static int imx_card_parse_of(struct imx_card_data *data) link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1; /* sai may support mclk/bclk = 1 */ - if (of_find_property(np, "fsl,mclk-equal-bclk", NULL)) { + if (of_property_read_bool(np, "fsl,mclk-equal-bclk")) { link_data->one2one_ratio = true; } else { int i; diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index b80c57362fb8..85bd36fb68a2 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -149,7 +149,7 @@ static int imx_es8328_probe(struct platform_device *pdev) goto put_device; } - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) { ret = -ENOMEM; goto put_device; @@ -159,9 +159,13 @@ static int imx_es8328_probe(struct platform_device *pdev) data->jack_gpio = of_get_named_gpio(pdev->dev.of_node, "jack-gpio", 0); - data->dai.cpus = &comp[0]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + data->dai.cpus = + data->dai.platforms = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; @@ -172,7 +176,6 @@ static int imx_es8328_probe(struct platform_device *pdev) 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_CBP_CFP; diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index 6614b3447649..765dad607bf6 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -743,14 +743,12 @@ fail: return ret; } -static int imx_rpmsg_pcm_remove(struct platform_device *pdev) +static void imx_rpmsg_pcm_remove(struct platform_device *pdev) { struct rpmsg_info *info = platform_get_drvdata(pdev); if (info->rpmsg_wq) destroy_workqueue(info->rpmsg_wq); - - return 0; } #ifdef CONFIG_PM @@ -821,7 +819,7 @@ static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = { static struct platform_driver imx_pcm_rpmsg_driver = { .probe = imx_rpmsg_pcm_probe, - .remove = imx_rpmsg_pcm_remove, + .remove_new = imx_rpmsg_pcm_remove, .driver = { .name = IMX_PCM_DRV_NAME, .pm = &imx_rpmsg_pcm_pm_ops, diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 580a0d963f0e..26c22783927b 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -193,14 +193,12 @@ fail: return ret; } -static int imx_sgtl5000_remove(struct platform_device *pdev) +static void imx_sgtl5000_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(card); clk_put(data->codec_clk); - - return 0; } static const struct of_device_id imx_sgtl5000_dt_ids[] = { @@ -216,7 +214,7 @@ static struct platform_driver imx_sgtl5000_driver = { .of_match_table = imx_sgtl5000_dt_ids, }, .probe = imx_sgtl5000_probe, - .remove = imx_sgtl5000_remove, + .remove_new = imx_sgtl5000_remove, }; module_platform_driver(imx_sgtl5000_driver); diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 4446fba755b9..ab978431ac98 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,15 +26,19 @@ 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; } - data->dai.cpus = &comp[0]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + data->dai.cpus = + data->dai.platforms = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; @@ -45,7 +49,6 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) 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; diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index a082ae636a4f..40a4a2667394 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -311,12 +311,11 @@ static int psc_ac97_of_probe(struct platform_device *op) return 0; } -static int psc_ac97_of_remove(struct platform_device *op) +static void psc_ac97_of_remove(struct platform_device *op) { mpc5200_audio_dma_destroy(op); snd_soc_unregister_component(&op->dev); snd_soc_set_ac97_ops(NULL); - return 0; } /* Match table for of_platform binding */ @@ -329,7 +328,7 @@ MODULE_DEVICE_TABLE(of, psc_ac97_match); static struct platform_driver psc_ac97_driver = { .probe = psc_ac97_of_probe, - .remove = psc_ac97_of_remove, + .remove_new = psc_ac97_of_remove, .driver = { .name = "mpc5200-psc-ac97", .of_match_table = psc_ac97_match, diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 73f3e61f208a..413df413b5eb 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -210,11 +210,10 @@ static int psc_i2s_of_probe(struct platform_device *op) } -static int psc_i2s_of_remove(struct platform_device *op) +static void psc_i2s_of_remove(struct platform_device *op) { mpc5200_audio_dma_destroy(op); snd_soc_unregister_component(&op->dev); - return 0; } /* Match table for of_platform binding */ @@ -227,7 +226,7 @@ MODULE_DEVICE_TABLE(of, psc_i2s_match); static struct platform_driver psc_i2s_driver = { .probe = psc_i2s_of_probe, - .remove = psc_i2s_of_remove, + .remove_new = psc_i2s_of_remove, .driver = { .name = "mpc5200-psc-i2s", .of_match_table = psc_i2s_match, diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index e71a992fbf93..ea2076ea8afe 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -387,7 +387,7 @@ error_alloc: * * This function is called when the platform device is removed. */ -static int mpc8610_hpcd_remove(struct platform_device *pdev) +static void mpc8610_hpcd_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct mpc8610_hpcd_data *machine_data = @@ -395,13 +395,11 @@ static int mpc8610_hpcd_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(machine_data); - - return 0; } static struct platform_driver mpc8610_hpcd_driver = { .probe = mpc8610_hpcd_probe, - .remove = mpc8610_hpcd_remove, + .remove_new = mpc8610_hpcd_remove, .driver = { /* The name must match 'compatible' property in the device tree, * in lowercase letters. diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index b45742931b0d..0b1418abeb9c 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -396,7 +396,7 @@ error_put: * * This function is called when the platform device is removed. */ -static int p1022_ds_remove(struct platform_device *pdev) +static void p1022_ds_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct machine_data *mdata = @@ -404,13 +404,11 @@ static int p1022_ds_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(mdata); - - return 0; } static struct platform_driver p1022_ds_driver = { .probe = p1022_ds_probe, - .remove = p1022_ds_remove, + .remove_new = p1022_ds_remove, .driver = { /* * The name must match 'compatible' property in the device tree, diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c index b395adabe823..4d85b742114c 100644 --- a/sound/soc/fsl/p1022_rdk.c +++ b/sound/soc/fsl/p1022_rdk.c @@ -345,7 +345,7 @@ error_put: * * This function is called when the platform device is removed. */ -static int p1022_rdk_remove(struct platform_device *pdev) +static void p1022_rdk_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct machine_data *mdata = @@ -353,13 +353,11 @@ static int p1022_rdk_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(mdata); - - return 0; } static struct platform_driver p1022_rdk_driver = { .probe = p1022_rdk_probe, - .remove = p1022_rdk_remove, + .remove_new = p1022_rdk_remove, .driver = { /* * The name must match 'compatible' property in the device tree, diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 997c3e66c636..d24c02e90878 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -109,14 +109,12 @@ static int pcm030_fabric_probe(struct platform_device *op) } -static int pcm030_fabric_remove(struct platform_device *op) +static void pcm030_fabric_remove(struct platform_device *op) { struct pcm030_audio_data *pdata = platform_get_drvdata(op); snd_soc_unregister_card(pdata->card); platform_device_unregister(pdata->codec_device); - - return 0; } static const struct of_device_id pcm030_audio_match[] = { @@ -127,7 +125,7 @@ MODULE_DEVICE_TABLE(of, pcm030_audio_match); static struct platform_driver pcm030_fabric_driver = { .probe = pcm030_fabric_probe, - .remove = pcm030_fabric_remove, + .remove_new = pcm030_fabric_remove, .driver = { .name = DRV_NAME, .of_match_table = pcm030_audio_match, |