From a76d7f5454c688b52dc849e832cc4c6dd0975723 Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Fri, 3 Nov 2017 16:35:44 -0400 Subject: [PATCH 1/6] ASoC: AMD: Make the driver name consistent across files This fixes the issue of driver not getting auto loaded with MODULE_ALIAS. find /sys/devices -name modalias -print0 | xargs -0 grep 'audio' /sys/devices/pci0000:00/0000:00:01.0/acp_audio_dma.0.auto/modalias:platform:acp_audio_dma BUG=b:62103837 TEST=boot and check for device in lsmod Signed-off-by: Akshu Agrawal Reviewed-on: https://chromium-review.googlesource.com/678278 Tested-by: Jason Clinton Reviewed-by: Jason Clinton Signed-off-by: Alex Deucher Signed-off-by: Mark Brown --- sound/soc/amd/Makefile | 4 ++-- sound/soc/amd/acp-pcm-dma.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile index eed64ff6c73e..f07fd2e2870a 100644 --- a/sound/soc/amd/Makefile +++ b/sound/soc/amd/Makefile @@ -1,5 +1,5 @@ -snd-soc-acp-pcm-objs := acp-pcm-dma.o +acp_audio_dma-objs := acp-pcm-dma.o snd-soc-acp-rt5645-mach-objs := acp-rt5645.o -obj-$(CONFIG_SND_SOC_AMD_ACP) += snd-soc-acp-pcm.o +obj-$(CONFIG_SND_SOC_AMD_ACP) += acp_audio_dma.o obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index 73b58ee00383..95c61ecdd1dd 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -40,6 +40,8 @@ #define ST_MAX_BUFFER (ST_PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) #define ST_MIN_BUFFER ST_MAX_BUFFER +#define DRV_NAME "acp_audio_dma" + static const struct snd_pcm_hardware acp_pcm_hardware_playback = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | @@ -1170,7 +1172,7 @@ static struct platform_driver acp_dma_driver = { .probe = acp_audio_probe, .remove = acp_audio_remove, .driver = { - .name = "acp_audio_dma", + .name = DRV_NAME, .pm = &acp_pm_ops, }, }; @@ -1181,4 +1183,4 @@ MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com"); MODULE_DESCRIPTION("AMD ACP PCM Driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:acp-dma-audio"); +MODULE_ALIAS("platform:"DRV_NAME); From 79b4885967cff17e0344b451e8fc4782013f0c9c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 Nov 2017 06:06:15 +0000 Subject: [PATCH 2/6] ASoC: use snd_soc_component_init_regmap() on 88pm860x To setup regmap, ALSA SoC has snd_soc_component_init_regmap() and .get_regmap. But these are duplicated feature. Let's use snd_soc_component_init_regmap() and remove .get_regmap Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/88pm860x-codec.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 848c5fe49bc7..be8ea723dff9 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -1319,6 +1319,7 @@ static int pm860x_probe(struct snd_soc_codec *codec) int i, ret; pm860x->codec = codec; + snd_soc_codec_init_regmap(codec, pm860x->regmap); for (i = 0; i < 4; i++) { ret = request_threaded_irq(pm860x->irq[i], NULL, @@ -1348,18 +1349,10 @@ static int pm860x_remove(struct snd_soc_codec *codec) return 0; } -static struct regmap *pm860x_get_regmap(struct device *dev) -{ - struct pm860x_priv *pm860x = dev_get_drvdata(dev); - - return pm860x->regmap; -} - static const struct snd_soc_codec_driver soc_codec_dev_pm860x = { .probe = pm860x_probe, .remove = pm860x_remove, .set_bias_level = pm860x_set_bias_level, - .get_regmap = pm860x_get_regmap, .component_driver = { .controls = pm860x_snd_controls, From 4b952275d2e7c6b32671a121ea5303a467bf2a0f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 Nov 2017 06:06:44 +0000 Subject: [PATCH 3/6] ASoC: use snd_soc_component_init_regmap() on atmel-classd To setup regmap, ALSA SoC has snd_soc_component_init_regmap() and .get_regmap. But these are duplicated feature. This driver is using .get_regmap and set regmap by using dev_get_regmap(), but it is automatically done by snd_soc_component_add_unlocked(). let's remove .get_regmap. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 8445edd06737..ebabed69f0e6 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -308,15 +308,9 @@ static int atmel_classd_codec_resume(struct snd_soc_codec *codec) return regcache_sync(dd->regmap); } -static struct regmap *atmel_classd_codec_get_remap(struct device *dev) -{ - return dev_get_regmap(dev, NULL); -} - static struct snd_soc_codec_driver soc_codec_dev_classd = { .probe = atmel_classd_codec_probe, .resume = atmel_classd_codec_resume, - .get_regmap = atmel_classd_codec_get_remap, .component_driver = { .controls = atmel_classd_snd_controls, .num_controls = ARRAY_SIZE(atmel_classd_snd_controls), From 7afa535eb107d587b22ffbbbaaeb4a0b87b94496 Mon Sep 17 00:00:00 2001 From: "Mukunda, Vijendar" Date: Mon, 4 Dec 2017 20:46:24 +0530 Subject: [PATCH 4/6] ASoC: amd: added error checks in dma driver added additional error checks in acp dma driver v2: printed error codes for acp init & acp deinit failure cases. Signed-off-by: Vijendar Mukunda Signed-off-by: Mark Brown --- sound/soc/amd/acp-pcm-dma.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index b5e41df6bb3a..c33a512283a4 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -850,6 +850,9 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct audio_substream_data *rtd = runtime->private_data; + if (!rtd) + return -EINVAL; + buffersize = frames_to_bytes(runtime, runtime->buffer_size); bytescount = acp_get_byte_count(rtd->acp_mmio, substream->stream); @@ -875,6 +878,8 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct audio_substream_data *rtd = runtime->private_data; + if (!rtd) + return -EINVAL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { config_acp_dma_channel(rtd->acp_mmio, SYSRAM_TO_ACP_CH_NUM, PLAYBACK_START_DMA_DESCR_CH12, @@ -1091,7 +1096,11 @@ static int acp_audio_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, audio_drv_data); /* Initialize the ACP */ - acp_init(audio_drv_data->acp_mmio, audio_drv_data->asic_type); + status = acp_init(audio_drv_data->acp_mmio, audio_drv_data->asic_type); + if (status) { + dev_err(&pdev->dev, "ACP Init failed status:%d\n", status); + return status; + } status = snd_soc_register_platform(&pdev->dev, &acp_asoc_platform); if (status != 0) { @@ -1108,9 +1117,12 @@ static int acp_audio_probe(struct platform_device *pdev) static int acp_audio_remove(struct platform_device *pdev) { + int status; struct audio_drv_data *adata = dev_get_drvdata(&pdev->dev); - acp_deinit(adata->acp_mmio); + status = acp_deinit(adata->acp_mmio); + if (status) + dev_err(&pdev->dev, "ACP Deinit failed status:%d\n", status); snd_soc_unregister_platform(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -1120,9 +1132,14 @@ static int acp_audio_remove(struct platform_device *pdev) static int acp_pcm_resume(struct device *dev) { u16 bank; + int status; struct audio_drv_data *adata = dev_get_drvdata(dev); - acp_init(adata->acp_mmio, adata->asic_type); + status = acp_init(adata->acp_mmio, adata->asic_type); + if (status) { + dev_err(dev, "ACP Init failed status:%d\n", status); + return status; + } if (adata->play_stream && adata->play_stream->runtime) { /* For Stoney, Memory gating is disabled,i.e SRAM Banks @@ -1154,18 +1171,26 @@ static int acp_pcm_resume(struct device *dev) static int acp_pcm_runtime_suspend(struct device *dev) { + int status; struct audio_drv_data *adata = dev_get_drvdata(dev); - acp_deinit(adata->acp_mmio); + status = acp_deinit(adata->acp_mmio); + if (status) + dev_err(dev, "ACP Deinit failed status:%d\n", status); acp_reg_write(0, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); return 0; } static int acp_pcm_runtime_resume(struct device *dev) { + int status; struct audio_drv_data *adata = dev_get_drvdata(dev); - acp_init(adata->acp_mmio, adata->asic_type); + status = acp_init(adata->acp_mmio, adata->asic_type); + if (status) { + dev_err(dev, "ACP Init failed status:%d\n", status); + return status; + } acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); return 0; } From e5acfc7d3562ae251cb786b5b52d4345dd16a02c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 5 Dec 2017 04:23:05 +0000 Subject: [PATCH 5/6] ASoC: don't use rtd->codec on snd_soc_new_compress() rtd->codec will be removed soon. rtd->codec = rtd->codec_dai->codec, thus, we can use rtd->codec_dai->component instead of it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index d9b1e6417fb9..81232f4ab614 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -1096,7 +1096,6 @@ static struct snd_compr_ops soc_compr_dyn_ops = { */ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) { - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_platform *platform = rtd->platform; struct snd_soc_component *component; struct snd_soc_rtdcom_list *rtdcom; @@ -1199,8 +1198,9 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) ret = snd_compress_new(rtd->card->snd_card, num, direction, new_name, compr); if (ret < 0) { + component = rtd->codec_dai->component; pr_err("compress asoc: can't create compress for codec %s\n", - codec->component.name); + component->name); goto compr_err; } From 7fb59e940f6225beed0b24cd09e9fad9aebb7565 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 5 Jan 2018 12:39:57 -0800 Subject: [PATCH 6/6] ASoC: codecs: dmic: Make number of channels configurable The DMIC DAI driver specifies a number of 1 to 8 channels for each DAI. The actual number of mics can currently not be configured in the device tree or audio glue, but is derived from the min/max channels of the CPU and codec DAI. A typical CPU DAI has two or more channels, in consequence a single mic is treated as a stereo/multi channel device, even though only one channel carries audio data. This change adds the option to specify the number of used DMIC channels in the device tree. When specified this value overwrites the default channels_max value of 8 in the snd_soc_dai_driver struct of the codec. Signed-off-by: Matthias Kaehlcke Reviewed-by: Rob Herring Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/dmic.txt | 2 ++ sound/soc/codecs/dmic.c | 24 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/dmic.txt b/Documentation/devicetree/bindings/sound/dmic.txt index 54c8ef6498a8..f7bf65611453 100644 --- a/Documentation/devicetree/bindings/sound/dmic.txt +++ b/Documentation/devicetree/bindings/sound/dmic.txt @@ -7,10 +7,12 @@ Required properties: Optional properties: - dmicen-gpios: GPIO specifier for dmic to control start and stop + - num-channels: Number of microphones on this DAI Example node: dmic_codec: dmic@0 { compatible = "dmic-codec"; dmicen-gpios = <&gpio4 3 GPIO_ACTIVE_HIGH>; + num-channels = <1>; }; diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index b88a1ee66f80..c88f974ebe3e 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -107,8 +107,30 @@ static const struct snd_soc_codec_driver soc_dmic = { static int dmic_dev_probe(struct platform_device *pdev) { + int err; + u32 chans; + struct snd_soc_dai_driver *dai_drv = &dmic_dai; + + if (pdev->dev.of_node) { + err = of_property_read_u32(pdev->dev.of_node, "num-channels", &chans); + if (err && (err != -ENOENT)) + return err; + + if (!err) { + if (chans < 1 || chans > 8) + return -EINVAL; + + dai_drv = devm_kzalloc(&pdev->dev, sizeof(*dai_drv), GFP_KERNEL); + if (!dai_drv) + return -ENOMEM; + + memcpy(dai_drv, &dmic_dai, sizeof(*dai_drv)); + dai_drv->capture.channels_max = chans; + } + } + return snd_soc_register_codec(&pdev->dev, - &soc_dmic, &dmic_dai, 1); + &soc_dmic, dai_drv, 1); } static int dmic_dev_remove(struct platform_device *pdev)