From 0650857570d161486a95d37bc8682628881ae2da Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 14:02:51 -0500 Subject: [PATCH 001/428] ALSA: hda: add autodetection for SoundWire When an ACPI companion device is present and the SoundWire link mask information is available, use SoundWire instead of legacy HDA or Skylake drivers. The SOF driver is selected when SoundWire or DMIC are detected. There is no precedence at this level. In the SOF driver proper, SoundWire will be handled first since it is mutually exclusive with HDaudio. Known devices with an existing DMI quirk bypass this detection to avoid any dependency on ACPI/DSDT tables. Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Bard Liao Reviewed-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200409190251.16569-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/intel-dsp-config.c | 97 ++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index be1df80ed013..1c1fdab2a55f 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -1,10 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019 Jaroslav Kysela +#include #include #include #include #include +#include +#include #include #include #include @@ -14,9 +17,13 @@ static int dsp_driver; module_param(dsp_driver, int, 0444); MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF)"); -#define FLAG_SST BIT(0) -#define FLAG_SOF BIT(1) -#define FLAG_SOF_ONLY_IF_DMIC BIT(16) +#define FLAG_SST BIT(0) +#define FLAG_SOF BIT(1) +#define FLAG_SOF_ONLY_IF_DMIC BIT(16) +#define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17) + +#define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \ + FLAG_SOF_ONLY_IF_SOUNDWIRE) struct config_entry { u32 flags; @@ -166,7 +173,7 @@ static const struct config_entry config_table[] = { } }, { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x9dc8, }, #endif @@ -187,7 +194,7 @@ static const struct config_entry config_table[] = { } }, { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0xa348, }, #endif @@ -204,18 +211,50 @@ static const struct config_entry config_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Google"), } }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") + }, + }, + { + /* early version of SKU 09C6 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") + }, + }, {} } }, { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x02c8, }, #endif /* Cometlake-H */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H) { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, + .flags = FLAG_SOF, + .device = 0x06c8, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), + }, + }, + {} + } + }, + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x06c8, }, #endif @@ -236,7 +275,7 @@ static const struct config_entry config_table[] = { } }, { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x34c8, }, #endif @@ -256,9 +295,8 @@ static const struct config_entry config_table[] = { {} } }, - { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0xa0c8, }, #endif @@ -303,6 +341,28 @@ static int snd_intel_dsp_check_dmic(struct pci_dev *pci) return ret; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) +static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) +{ + struct sdw_intel_acpi_info info; + acpi_handle handle; + int ret; + + handle = ACPI_HANDLE(&pci->dev); + + ret = sdw_intel_acpi_scan(handle, &info); + if (ret < 0) + return ret; + + return info.link_mask; +} +#else +static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) +{ + return 0; +} +#endif + int snd_intel_dsp_driver_probe(struct pci_dev *pci) { const struct config_entry *cfg; @@ -336,14 +396,18 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) return SND_INTEL_DSP_DRIVER_ANY; if (cfg->flags & FLAG_SOF) { - if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC) { - if (snd_intel_dsp_check_dmic(pci)) { - dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); - return SND_INTEL_DSP_DRIVER_SOF; - } - } else { + if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && + snd_intel_dsp_check_soundwire(pci) > 0) { + dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); return SND_INTEL_DSP_DRIVER_SOF; } + if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && + snd_intel_dsp_check_dmic(pci)) { + dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); + return SND_INTEL_DSP_DRIVER_SOF; + } + if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) + return SND_INTEL_DSP_DRIVER_SOF; } if (cfg->flags & FLAG_SST) @@ -355,3 +419,4 @@ EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel DSP config driver"); +MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); From 1d03c19e970e7457b755d736a81e9e8601e1a407 Mon Sep 17 00:00:00 2001 From: Payal Kshirsagar Date: Thu, 9 Apr 2020 13:48:52 -0500 Subject: [PATCH 002/428] ASoC: SOF: remove unneeded variables Remove unneeded temporary local variables and their declarations. Change suggested by coccinelle. Signed-off-by: Payal Kshirsagar Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200409184853.15896-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 5 +---- sound/soc/sof/nocodec.c | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 3041fbbb010a..7e7e296a3953 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -207,7 +207,6 @@ EXPORT_SYMBOL_NS(hda_codec_i915_init, SND_SOC_SOF_HDA_AUDIO_CODEC_I915); int hda_codec_i915_exit(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); - int ret; if (!bus->audio_component) return 0; @@ -215,9 +214,7 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev) /* power down unconditionally */ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); - ret = snd_hdac_i915_exit(bus); - - return ret; + return snd_hdac_i915_exit(bus); } EXPORT_SYMBOL_NS(hda_codec_i915_exit, SND_SOC_SOF_HDA_AUDIO_CODEC_I915); diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 2233146386cc..5bf67b2aa4e7 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -66,7 +66,6 @@ int sof_nocodec_setup(struct device *dev, const struct snd_sof_dsp_ops *ops) { struct snd_soc_dai_link *links; - int ret; /* create dummy BE dai_links */ links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * @@ -74,9 +73,8 @@ int sof_nocodec_setup(struct device *dev, if (!links) return -ENOMEM; - ret = sof_nocodec_bes_setup(dev, ops, links, ops->num_drv, - &sof_nocodec_card); - return ret; + return sof_nocodec_bes_setup(dev, ops, links, ops->num_drv, + &sof_nocodec_card); } EXPORT_SYMBOL(sof_nocodec_setup); From 805a23de2657c10c2ca96588a309a42df947bb36 Mon Sep 17 00:00:00 2001 From: Payal Kshirsagar Date: Thu, 9 Apr 2020 13:48:53 -0500 Subject: [PATCH 003/428] ASoC: SOF: Intel: hda: remove unnecessary parentheses Remove unnecessary parentheses around the right hand side of an assignment and align the code. Signed-off-by: Payal Kshirsagar Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200409184853.15896-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 99087b6afb67..c780e1e6f895 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -226,10 +226,10 @@ bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS); - is_enable = ((val & HDA_DSP_ADSPCS_CPA_MASK(core_mask)) && - (val & HDA_DSP_ADSPCS_SPA_MASK(core_mask)) && - !(val & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) && - !(val & HDA_DSP_ADSPCS_CSTALL_MASK(core_mask))); + is_enable = (val & HDA_DSP_ADSPCS_CPA_MASK(core_mask)) && + (val & HDA_DSP_ADSPCS_SPA_MASK(core_mask)) && + !(val & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) && + !(val & HDA_DSP_ADSPCS_CSTALL_MASK(core_mask)); dev_dbg(sdev->dev, "DSP core(s) enabled? %d : core_mask %x\n", is_enable, core_mask); From 110f44c2ed1be38efff72f078134aea6678adaa8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:44:13 -0500 Subject: [PATCH 004/428] ASoC: codecs: rt1308-sdw: reduce verbosity These messages are generated at each enumeration, this is overkill. Move to dev_dbg [ 86.481709] rt1308 sdw:1:25d:1308:0: rt1308_io_init m_btl_l=0xffee, m_btl_r=0xffff [ 86.481714] rt1308 sdw:1:25d:1308:0: rt1308_io_init c_btl_l=0x28c, c_btl_r=0x113 Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200409184416.15591-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index a5a7e46de246..1502a22b0d4a 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -235,9 +235,9 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave) efuse_c_btl_r = tmp; regmap_read(rt1308->regmap, 0xc872, &tmp); efuse_c_btl_r = efuse_c_btl_r | (tmp << 8); - dev_info(&slave->dev, "%s m_btl_l=0x%x, m_btl_r=0x%x\n", __func__, + dev_dbg(&slave->dev, "%s m_btl_l=0x%x, m_btl_r=0x%x\n", __func__, efuse_m_btl_l, efuse_m_btl_r); - dev_info(&slave->dev, "%s c_btl_l=0x%x, c_btl_r=0x%x\n", __func__, + dev_dbg(&slave->dev, "%s c_btl_l=0x%x, c_btl_r=0x%x\n", __func__, efuse_c_btl_l, efuse_c_btl_r); /* initial settings */ From 0d4453e98706d996ba06aa38907eab989822f6ee Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:44:14 -0500 Subject: [PATCH 005/428] ASoC: SOF: Intel: hda: reduce verbosity on SoundWire detection No need to report an error when SoundWire is not detected (not present in hardware or not exposed in ACPI). Move to dev_dbg to state that SoundWire is skipped. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200409184416.15591-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 211e91e79eae..6cbe2edc868c 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -135,10 +135,8 @@ static int hda_sdw_acpi_scan(struct snd_sof_dev *sdev) hdev = sdev->pdata->hw_pdata; ret = sdw_intel_acpi_scan(handle, &hdev->info); - if (ret < 0) { - dev_err(sdev->dev, "%s failed\n", __func__); + if (ret < 0) return -EINVAL; - } return 0; } @@ -604,7 +602,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) /* scan SoundWire capabilities exposed by DSDT */ ret = hda_sdw_acpi_scan(sdev); if (ret < 0) { - dev_dbg(sdev->dev, "skipping SoundWire, ACPI scan error\n"); + dev_dbg(sdev->dev, "skipping SoundWire, not detected with ACPI scan\n"); goto skip_soundwire; } From 642646cc4f84e1a7a0002f8ac4660576011abffe Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:44:15 -0500 Subject: [PATCH 006/428] ASoC: SOF: Intel: hda: log number of microphones detected in NHLT tables Log the information extracted from NHLT tables to help support users who report non-functional digital mics with SOF. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200409184416.15591-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 6cbe2edc868c..263937357ea3 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1006,6 +1006,10 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) if (!tplg_filename) return -EINVAL; + dev_info(bus->dev, + "DMICs detected in NHLT tables: %d\n", + dmic_num); + pdata->machine = hda_mach; pdata->tplg_filename = tplg_filename; } From b2acc24c805a42b6ebfe8b8ae09dbf9c994c5604 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 9 Apr 2020 13:44:16 -0500 Subject: [PATCH 007/428] ASoC: soc-core: Add dynamic debug logs in soc_dai_link_sanity_check() When a platform device is created successfully but the machine driver probe fails due to errors with missing components during the card bind stage, no error is propagated or logged. To help flag such problems, add a dynamic debug log. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200409184416.15591-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 843b8b1c89d4..8b2f6dd2fc8e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -865,8 +865,12 @@ static int soc_dai_link_sanity_check(struct snd_soc_card *card, * Defer card registration if codec component is not added to * component list. */ - if (!soc_find_component(codec)) + if (!soc_find_component(codec)) { + dev_dbg(card->dev, + "ASoC: codec component %s not found for link %s\n", + codec->name, link->name); return -EPROBE_DEFER; + } } for_each_link_platforms(link, i, platform) { @@ -886,8 +890,12 @@ static int soc_dai_link_sanity_check(struct snd_soc_card *card, * Defer card registration if platform component is not added to * component list. */ - if (!soc_find_component(platform)) + if (!soc_find_component(platform)) { + dev_dbg(card->dev, + "ASoC: platform component %s not found for link %s\n", + platform->name, link->name); return -EPROBE_DEFER; + } } for_each_link_cpus(link, i, cpu) { @@ -908,8 +916,12 @@ static int soc_dai_link_sanity_check(struct snd_soc_card *card, * component list. */ if ((cpu->of_node || cpu->name) && - !soc_find_component(cpu)) + !soc_find_component(cpu)) { + dev_dbg(card->dev, + "ASoC: cpu component %s not found for link %s\n", + cpu->name, link->name); return -EPROBE_DEFER; + } /* * At least one of CPU DAI name or CPU device name/node must be From c2233a266178f8937cc26a84cd7672334b5424b7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Mar 2020 10:47:37 +0900 Subject: [PATCH 008/428] ASoC: soc: use asoc_rtd_to_cpu() / asoc_rtd_to_codec() macro for DAI pointer Signed-off-by: Kuninori Morimoto Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87imimboli.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 12 ++++----- sound/soc/soc-compress.c | 36 +++++++++++++-------------- sound/soc/soc-core.c | 16 ++++++------ sound/soc/soc-dapm.c | 4 +-- sound/soc/soc-generic-dmaengine-pcm.c | 6 ++--- sound/soc/soc-pcm.c | 30 +++++++++++----------- 6 files changed, 52 insertions(+), 52 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 13458e4fbb13..4dff6745b067 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1179,16 +1179,16 @@ struct snd_soc_pcm_runtime { (i)++) #define for_each_rtd_cpu_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \ + ((i) < rtd->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \ (i)++) #define for_each_rtd_cpu_dais_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);) + for (; (--(i) >= 0) && ((dai) = asoc_rtd_to_cpu(rtd, i));) #define for_each_rtd_codec_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \ + ((i) < rtd->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \ (i)++) #define for_each_rtd_codec_dais_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);) + for (; (--(i) >= 0) && ((dai) = asoc_rtd_to_codec(rtd, i));) #define for_each_rtd_dais(rtd, i, dai) \ for ((i) = 0; \ ((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \ @@ -1381,8 +1381,8 @@ struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd; list_for_each_entry(rtd, &card->rtd_list, list) { - if (!strcmp(rtd->codec_dai->name, dai_name)) - return rtd->codec_dai; + if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) + return asoc_rtd_to_codec(rtd, 0); } return NULL; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 50062eb79adb..3f77c0208e09 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -73,7 +73,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component, *save = NULL; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret, i; for_each_rtd_components(rtd, i, component) { @@ -141,7 +141,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) struct snd_pcm_substream *fe_substream = fe->pcm->streams[cstream->direction].substream; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; int stream; @@ -230,8 +230,8 @@ static int soc_compr_free(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int stream, i; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -274,7 +274,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) static int soc_compr_free_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); struct snd_soc_dpcm *dpcm; int stream, ret; @@ -343,8 +343,8 @@ static int soc_compr_components_trigger(struct snd_compr_stream *cstream, static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -373,7 +373,7 @@ out: static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); int ret, stream; if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN || @@ -446,7 +446,7 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, struct snd_compr_params *params) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -500,7 +500,7 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, struct snd_soc_pcm_runtime *fe = cstream->private_data; struct snd_pcm_substream *fe_substream = fe->pcm->streams[cstream->direction].substream; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); int ret, stream; if (cstream->direction == SND_COMPRESS_PLAYBACK) @@ -558,7 +558,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret = 0; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -632,7 +632,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret = 0; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -664,7 +664,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; int i, ret = 0; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -711,7 +711,7 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream, { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret; if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) { @@ -739,7 +739,7 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret; if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) { @@ -801,8 +801,8 @@ 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_component *component; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_compr *compr; struct snd_pcm *be_pcm; char new_name[64]; @@ -891,7 +891,7 @@ 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; + component = asoc_rtd_to_codec(rtd, 0)->component; dev_err(component->dev, "Compress ASoC: can't create compress for codec %s: %d\n", component->name, ret); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 843b8b1c89d4..4ad64b96d893 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -364,7 +364,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); */ void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int playback = SNDRV_PCM_STREAM_PLAYBACK; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -991,13 +991,13 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, rtd->num_cpus = dai_link->num_cpus; for_each_link_cpus(dai_link, i, cpu) { - rtd->cpu_dais[i] = snd_soc_find_dai(cpu); - if (!rtd->cpu_dais[i]) { + asoc_rtd_to_cpu(rtd, i) = snd_soc_find_dai(cpu); + if (!asoc_rtd_to_cpu(rtd, i)) { dev_info(card->dev, "ASoC: CPU DAI %s not registered\n", cpu->dai_name); goto _err_defer; } - snd_soc_rtd_add_component(rtd, rtd->cpu_dais[i]->component); + snd_soc_rtd_add_component(rtd, asoc_rtd_to_cpu(rtd, i)->component); } /* Single cpu links expect cpu and cpu_dai in runtime data */ @@ -1006,14 +1006,14 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, /* Find CODEC from registered CODECs */ rtd->num_codecs = dai_link->num_codecs; for_each_link_codecs(dai_link, i, codec) { - rtd->codec_dais[i] = snd_soc_find_dai(codec); - if (!rtd->codec_dais[i]) { + asoc_rtd_to_codec(rtd, i) = snd_soc_find_dai(codec); + if (!asoc_rtd_to_codec(rtd, i)) { dev_info(card->dev, "ASoC: CODEC DAI %s not registered\n", codec->dai_name); goto _err_defer; } - snd_soc_rtd_add_component(rtd, rtd->codec_dais[i]->component); + snd_soc_rtd_add_component(rtd, asoc_rtd_to_codec(rtd, i)->component); } /* Single codec links expect codec and codec_dai in runtime data */ @@ -1062,7 +1062,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai_link *dai_link = rtd->dai_link; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_component *component; int ret, num, i; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 679ed60d850e..8f260994b149 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4370,11 +4370,11 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, if (rtd->num_cpus == 1) { for_each_rtd_codec_dais(rtd, i, codec_dai) dapm_add_valid_dai_widget(card, rtd, codec_dai, - rtd->cpu_dais[0]); + asoc_rtd_to_cpu(rtd, 0)); } else if (rtd->num_codecs == rtd->num_cpus) { for_each_rtd_codec_dais(rtd, i, codec_dai) dapm_add_valid_dai_widget(card, rtd, codec_dai, - rtd->cpu_dais[i]); + asoc_rtd_to_cpu(rtd, i)); } else { dev_err(card->dev, "N cpus to M codecs link is not supported yet\n"); diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index facf1922a714..f728309a0833 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -68,7 +68,7 @@ int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, return -EINVAL; } - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); if (ret) @@ -134,7 +134,7 @@ dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component, return snd_soc_set_runtime_hwparams(substream, pcm->config->pcm_hardware); - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); memset(&hw, 0, sizeof(hw)); hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | @@ -203,7 +203,7 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel( return NULL; } - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0]) return pcm->chan[0]; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 289aebc15529..454735f8fa92 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -136,7 +136,7 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, return -ENOMEM; for_each_pcm_streams(stream) - if (snd_soc_dai_stream_valid(fe->cpu_dai, stream)) + if (snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream)) offset += dpcm_show_state(fe, stream, buf + offset, out_count - offset); @@ -836,10 +836,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) soc_pcm_init_runtime_hw(substream); if (rtd->num_codecs == 1) - codec_dai_name = rtd->codec_dai->name; + codec_dai_name = asoc_rtd_to_codec(rtd, 0)->name; if (rtd->num_cpus == 1) - cpu_dai_name = rtd->cpu_dai->name; + cpu_dai_name = asoc_rtd_to_cpu(rtd, 0)->name; if (soc_pcm_has_symmetry(substream)) runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; @@ -1483,7 +1483,7 @@ static bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list) { - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); int paths; if (fe->num_cpus > 1) { @@ -1842,7 +1842,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, * DAIs connected to a single CPU DAI, use CPU DAI's directly */ if (be->num_codecs == 1) { - codec_stream = snd_soc_dai_get_pcm_stream(be->codec_dais[0], stream); + codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream); *channels_min = max(*channels_min, codec_stream->channels_min); @@ -2759,7 +2759,7 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) return 0; /* only check active links */ - if (!fe->cpu_dai->active) + if (!asoc_rtd_to_cpu(fe, 0)->active) return 0; /* DAPM sync will call this to update DSP paths */ @@ -2769,13 +2769,13 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) for_each_pcm_streams(stream) { /* skip if FE doesn't have playback/capture capability */ - if (!snd_soc_dai_stream_valid(fe->cpu_dai, stream) || - !snd_soc_dai_stream_valid(fe->codec_dai, stream)) + if (!snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream) || + !snd_soc_dai_stream_valid(asoc_rtd_to_codec(fe, 0), stream)) continue; /* skip if FE isn't currently playing/capturing */ - if (!fe->cpu_dai->stream_active[stream] || - !fe->codec_dai->stream_active[stream]) + if (!asoc_rtd_to_cpu(fe, 0)->stream_active[stream] || + !asoc_rtd_to_codec(fe, 0)->stream_active[stream]) continue; paths = dpcm_path_get(fe, stream, &list); @@ -2922,9 +2922,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) for_each_rtd_codec_dais(rtd, i, codec_dai) { if (rtd->num_cpus == 1) { - cpu_dai = rtd->cpu_dais[0]; + cpu_dai = asoc_rtd_to_cpu(rtd, 0); } else if (rtd->num_cpus == rtd->num_codecs) { - cpu_dai = rtd->cpu_dais[i]; + cpu_dai = asoc_rtd_to_cpu(rtd, i); } else { dev_err(rtd->card->dev, "N cpus to M codecs link is not supported yet\n"); @@ -2971,7 +2971,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) snprintf(new_name, sizeof(new_name), "%s %s-%d", rtd->dai_link->stream_name, (rtd->num_codecs > 1) ? - "multicodec" : rtd->codec_dai->name, num); + "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, num); ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, capture, &pcm); @@ -3050,8 +3050,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) pcm->no_device_suspend = true; out: dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", - (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, - (rtd->num_cpus > 1) ? "multicpu" : rtd->cpu_dai->name); + (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, + (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name); return ret; } From 49648d02008dd75ddd84b16f9abf29f24c383519 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Mar 2020 10:47:54 +0900 Subject: [PATCH 009/428] ASoC: soc-core: set rtd->num_cpu/codec at soc_new_pcm_runtime() rtd->cpu_dais/codec_dais are set at soc_new_pcm_runtime(). rtd->num_cpus/codecs should be set there. This patch do it. Signed-off-by: Kuninori Morimoto Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87h7y6bol1.wl-kuninori.morimoto.gx@renesas.com 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 4ad64b96d893..8cef4fd6df36 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -490,6 +490,8 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( */ rtd->cpu_dais = &rtd->dais[0]; rtd->codec_dais = &rtd->dais[dai_link->num_cpus]; + rtd->num_cpus = dai_link->num_cpus; + rtd->num_codecs = dai_link->num_codecs; /* * rtd remaining settings @@ -989,7 +991,6 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, if (!rtd) return -ENOMEM; - rtd->num_cpus = dai_link->num_cpus; for_each_link_cpus(dai_link, i, cpu) { asoc_rtd_to_cpu(rtd, i) = snd_soc_find_dai(cpu); if (!asoc_rtd_to_cpu(rtd, i)) { @@ -1004,7 +1005,6 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, rtd->cpu_dai = rtd->cpu_dais[0]; /* Find CODEC from registered CODECs */ - rtd->num_codecs = dai_link->num_codecs; for_each_link_codecs(dai_link, i, codec) { asoc_rtd_to_codec(rtd, i) = snd_soc_find_dai(codec); if (!asoc_rtd_to_codec(rtd, i)) { From 01faf501eefa86fa6f334bb9c71a48498de653e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Mar 2020 10:48:14 +0900 Subject: [PATCH 010/428] ASoC: soc-core: tidyup soc_new_pcm_runtime() rtd setups soc_new_pcm_runtime() setups rtd, but code is very random. This patch tidyup it. Signed-off-by: Kuninori Morimoto Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87ftdqbokh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8cef4fd6df36..4d617c495864 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -492,17 +492,12 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( rtd->codec_dais = &rtd->dais[dai_link->num_cpus]; rtd->num_cpus = dai_link->num_cpus; rtd->num_codecs = dai_link->num_codecs; - - /* - * rtd remaining settings - */ - rtd->card = card; - rtd->dai_link = dai_link; + rtd->card = card; + rtd->dai_link = dai_link; + rtd->num = card->num_rtd++; /* see for_each_card_rtds */ list_add_tail(&rtd->list, &card->rtd_list); - rtd->num = card->num_rtd; - card->num_rtd++; return rtd; From 1729025b04b9f242dca37f50dba8dd3705eb1ea1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Mar 2020 10:48:27 +0900 Subject: [PATCH 011/428] ASoC: soc-core: remove cpu_dai/codec_dai/cpu_dais/codec_dais No-one is using cpu_dai/codec_dai/cpu_dais/codec_dais. Let's remove these from snd_soc_pcm_runtime Signed-off-by: Kuninori Morimoto Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87eetabok4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 14 ++++++++------ sound/soc/soc-core.c | 11 +++-------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 4dff6745b067..a904086b8ef6 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1143,14 +1143,16 @@ struct snd_soc_pcm_runtime { /* runtime devices */ struct snd_pcm *pcm; struct snd_compr *compr; - struct snd_soc_dai *codec_dai; - struct snd_soc_dai *cpu_dai; + + /* + * dais = cpu_dai + codec_dai + * see + * soc_new_pcm_runtime() + * asoc_rtd_to_cpu() + * asoc_rtd_to_codec() + */ struct snd_soc_dai **dais; - - struct snd_soc_dai **codec_dais; unsigned int num_codecs; - - struct snd_soc_dai **cpu_dais; unsigned int num_cpus; struct delayed_work delayed_work; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4d617c495864..7ea9725e33b3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -487,9 +487,10 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( * dais = [][][][][][][][][][][][][][][][][][] * ^cpu_dais ^codec_dais * |--- num_cpus ---|--- num_codecs --| + * see + * asoc_rtd_to_cpu() + * asoc_rtd_to_codec() */ - rtd->cpu_dais = &rtd->dais[0]; - rtd->codec_dais = &rtd->dais[dai_link->num_cpus]; rtd->num_cpus = dai_link->num_cpus; rtd->num_codecs = dai_link->num_codecs; rtd->card = card; @@ -996,9 +997,6 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, snd_soc_rtd_add_component(rtd, asoc_rtd_to_cpu(rtd, i)->component); } - /* Single cpu links expect cpu and cpu_dai in runtime data */ - rtd->cpu_dai = rtd->cpu_dais[0]; - /* Find CODEC from registered CODECs */ for_each_link_codecs(dai_link, i, codec) { asoc_rtd_to_codec(rtd, i) = snd_soc_find_dai(codec); @@ -1011,9 +1009,6 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, snd_soc_rtd_add_component(rtd, asoc_rtd_to_codec(rtd, i)->component); } - /* Single codec links expect codec and codec_dai in runtime data */ - rtd->codec_dai = rtd->codec_dais[0]; - /* Find PLATFORM from registered PLATFORMs */ for_each_link_platforms(dai_link, i, platform) { for_each_component(component) { From a8bb72f160020db5d7f81824b2dba6c8e29ef67a Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Thu, 9 Apr 2020 13:58:15 -0500 Subject: [PATCH 012/428] ASoC: Intel: sof_da7219_max98373: Add BE dailink for dmic16k Add dmic16k BE dailink for keyword detection support, FE is added in topology tplg file. Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200409185827.16255-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219_max98373.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index b707dd3b5625..8b5b74ba349f 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -265,6 +265,9 @@ SND_SOC_DAILINK_DEF(dmic_pin, SND_SOC_DAILINK_DEF(dmic_codec, DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); +SND_SOC_DAILINK_DEF(dmic16k_pin, + 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, @@ -337,6 +340,14 @@ static struct snd_soc_dai_link dais[] = { .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, + { + .name = "dmic16k", + .id = 6, + .ignore_suspend = 1, + .dpcm_capture = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), + } }; static struct snd_soc_card card_da7219_m98373 = { From 3a24f135e6cc58c2dc042dde44031ec31b706ce5 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Thu, 9 Apr 2020 13:58:16 -0500 Subject: [PATCH 013/428] ASoC: intel/skl/hda - set autosuspend timeout for hda codecs On some Lenovo and HP laptops, if both codec driver and SOF driver are in runtime suspend mode, we plug a headset to the audio jack, the headphone could be detected but Mic couldn't. That is because when plugging, the headphone triggers a unsol event first, and about 0.7s later (on the Lenovo X1 Carbon 7th), the Mic triggers a unsol event. But if the codec driver enters runtime suspend within 0.7s, the Mic can't trigger the unsol event. If we don't set autosuspend_delay to a non-zero value for the hda codec driver, it will enter runtime suspend immediately after the headphone triggers the unsol event. Follow the sequence of legacy hda driver and set a autosuspend delay of 1sec after card registration (refer to pci/hda/hda_intel.c and pci/hda/hda_codec.c). Co-developed-by: Kai Vehmanen Co-developed-by: Jaska Uimonen Signed-off-by: Hui Wang Signed-off-by: Kai Vehmanen Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Clarex Zhou Link: https://lore.kernel.org/r/20200409185827.16255-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_generic.c | 29 +++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 3be764299ab0..64197b010e7d 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -113,6 +113,8 @@ static char hda_soc_components[30]; #define IDISP_ROUTE_COUNT (IDISP_DAI_COUNT * 2) #define IDISP_CODEC_MASK 0x4 +#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000 + static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) { struct snd_soc_card *card = &hda_soc_card; @@ -168,6 +170,27 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) return 0; } +static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card) +{ + struct snd_soc_pcm_runtime *rtd = + list_first_entry(&card->rtd_list, + struct snd_soc_pcm_runtime, list); + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct hdac_hda_priv *hda_pvt; + + if (!codec_dai) + return; + + /* + * all codecs are on the same bus, so it's sufficient + * to lookup the first runtime and its codec, and set + * power save defaults for all codecs on the bus + */ + hda_pvt = snd_soc_component_get_drvdata(codec_dai->component); + snd_hda_set_power_save(hda_pvt->codec.bus, + HDA_CODEC_AUTOSUSPEND_DELAY_MS); +} + static int skl_hda_audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach; @@ -206,7 +229,11 @@ static int skl_hda_audio_probe(struct platform_device *pdev) hda_soc_card.components = hda_soc_components; } - return devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); + ret = devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); + if (!ret) + skl_set_hda_codec_autosuspend_delay(&hda_soc_card); + + return ret; } static struct platform_driver skl_hda_audio = { From d233c4941630af0ec2e14be7c2a693e9c9ce3087 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Thu, 9 Apr 2020 13:58:17 -0500 Subject: [PATCH 014/428] ALSA: hda: Add ElkhartLake HDMI codec vid Add HDMI codec vid for the Intel ElkhartLake platform Signed-off-by: Libin Yang Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Bard Liao Acked-by: Takashi Iwai Link: https://lore.kernel.org/r/20200409185827.16255-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/pci/hda/patch_hdmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index bb287a916dae..403baca89452 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -4156,6 +4156,7 @@ HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi), HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi), HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), +HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), From a4ed29273376cb1f5aa05b90eb3c4d5877564976 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Thu, 9 Apr 2020 13:58:18 -0500 Subject: [PATCH 015/428] ASoC: SOF: Intel: add PCI ID for ElkhartLake Add PCI ID for ElkhartLake platform. Signed-off-by: Libin Yang Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20200409185827.16255-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index cec631a1389b..b5f0221d624f 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -435,6 +435,8 @@ static const struct pci_device_id sof_pci_ids[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) { PCI_DEVICE(0x8086, 0x4b55), .driver_data = (unsigned long)&ehl_desc}, + { PCI_DEVICE(0x8086, 0x4b58), + .driver_data = (unsigned long)&ehl_desc}, #endif { 0, } }; From db8cfae8c4fdffee9f287a9172605450b5c5bc2e Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Thu, 9 Apr 2020 13:58:19 -0500 Subject: [PATCH 016/428] ASoC: Intel: boards: support Elkhart Lake with rt5660 This patch adds the support of Intel Elkhart Lake with Realtek rt5660 codec. Signed-off-by: Libin Yang Signed-off-by: Muhammad Nazif Bin Mohd Borhan Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20200409185827.16255-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 15 + sound/soc/intel/boards/Makefile | 2 + sound/soc/intel/boards/ehl_rt5660.c | 323 ++++++++++++++++++ .../intel/common/soc-acpi-intel-ehl-match.c | 7 + 4 files changed, 347 insertions(+) create mode 100644 sound/soc/intel/boards/ehl_rt5660.c diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 556c3104e641..c57bc6d0f145 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -524,6 +524,21 @@ config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH endif ## SND_SOC_SOF_JASPERLAKE +if SND_SOC_SOF_ELKHARTLAKE + +config SND_SOC_INTEL_EHL_RT5660_MACH + tristate "EHL with RT5660 in I2S mode" + depends on I2C && ACPI + depends on MFD_INTEL_LPSS || COMPILE_TEST + depends on SND_HDA_CODEC_HDMI + select SND_SOC_RT5660 + select SND_SOC_DMIC + help + This adds support for ASoC machine driver for Elkhart Lake + platform with RT5660 I2S audio codec. + +endif ## SND_SOC_SOF_ELKHARTLAKE + if SND_SOC_SOF_INTEL_SOUNDWIRE config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 1ef6e60bc2a0..98bf42463a1b 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -31,6 +31,7 @@ snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o hda_dsp_c snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o hda_dsp_common.o +snd-soc-ehl-rt5660-objs := ehl_rt5660.o hda_dsp_common.o snd-soc-sof-sdw-objs += sof_sdw.o \ sof_sdw_rt711.o sof_sdw_rt700.o \ sof_sdw_rt1308.o sof_sdw_rt715.o \ @@ -68,4 +69,5 @@ obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max9 obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o obj-$(CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH) += snd-soc-skl_hda_dsp.o obj-$(CONFIG_SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH) += snd-soc-sof_da7219_max98373.o +obj-$(CONFIG_SND_SOC_INTEL_EHL_RT5660_MACH) += snd-soc-ehl-rt5660.o obj-$(CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH) += snd-soc-sof-sdw.o diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c new file mode 100644 index 000000000000..2e3244d5496b --- /dev/null +++ b/sound/soc/intel/boards/ehl_rt5660.c @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * ehl_rt5660 - ASOC Machine driver for Elkhart Lake platforms + * with rt5660 codec + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hda_dsp_common.h" +#include "../../codecs/rt5660.h" + +#define DUAL_CHANNEL 2 +#define HDMI_LINK_START 3 +#define HDMI_LINE_END 6 +#define NAME_SIZE 32 +#define IDISP_CODEC_MASK 0x4 + +struct sof_card_private { + struct list_head hdmi_pcm_list; + bool idisp_codec; +}; + +static const struct snd_kcontrol_new rt5660_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), + /* There are two MICBIAS in rt5660, each for one MIC */ + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Headset Mic2"), + SOC_DAPM_PIN_SWITCH("Line Out"), +}; + +static const struct snd_soc_dapm_widget rt5660_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Headset Mic2", NULL), + SND_SOC_DAPM_MIC("SoC DMIC", NULL), + SND_SOC_DAPM_LINE("Line Out", NULL), +}; + +static const struct snd_soc_dapm_route rt5660_map[] = { + {"Speaker", NULL, "SPO"}, + + {"Headset Mic", NULL, "MICBIAS1"}, + {"Headset Mic2", NULL, "MICBIAS2"}, + + {"IN1P", NULL, "Headset Mic"}, + {"IN2P", NULL, "Headset Mic2"}, + + {"Line Out", NULL, "LOUTL"}, + {"Line Out", NULL, "LOUTR"}, + + {"DMic", NULL, "SoC DMIC"}, +}; + +struct sof_hdmi_pcm { + struct list_head head; + struct snd_soc_dai *codec_dai; + int device; +}; + +static int hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); + struct sof_hdmi_pcm *pcm; + + pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); + if (!pcm) + return -ENOMEM; + + /* dai_link id is 1:1 mapped to the PCM device */ + pcm->device = rtd->dai_link->id; + pcm->codec_dai = dai; + + list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); + + return 0; +} + +static int card_late_probe(struct snd_soc_card *card) +{ + struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); + struct sof_hdmi_pcm *pcm; + + if (list_empty(&ctx->hdmi_pcm_list)) + return -ENOENT; + + if (!ctx->idisp_codec) + return 0; + + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head); + + return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component); +} + +static int rt5660_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, + RT5660_SCLK_S_PLL1, + params_rate(params) * 512, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT5660_PLL1_S_BCLK, + params_rate(params) * 50, + params_rate(params) * 512); + if (ret < 0) + dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret); + + return ret; +} + +static struct snd_soc_ops rt5660_ops = { + .hw_params = rt5660_hw_params, +}; + +SND_SOC_DAILINK_DEF(ssp0_pin, + DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); + +SND_SOC_DAILINK_DEF(rt5660_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5660:00", "rt5660-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); + +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(idisp4_pin, + DAILINK_COMP_ARRAY(COMP_CPU("iDisp4 Pin"))); +SND_SOC_DAILINK_DEF(idisp4_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi4"))); + +static struct snd_soc_dai_link ehl_rt5660_dailink[] = { + /* back ends */ + { + .name = "SSP0-Codec", + .id = 0, + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ops = &rt5660_ops, + .nonatomic = true, + SND_SOC_DAILINK_REG(ssp0_pin, rt5660_codec, platform), + }, + { + .name = "dmic48k", + .id = 1, + .ignore_suspend = 1, + .dpcm_capture = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), + }, + { + .name = "dmic16k", + .id = 2, + .ignore_suspend = 1, + .dpcm_capture = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform), + }, + { + .name = "iDisp1", + .id = 5, + .init = hdmi_init, + .dpcm_playback = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), + }, + { + .name = "iDisp2", + .id = 6, + .init = hdmi_init, + .dpcm_playback = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), + }, + { + .name = "iDisp3", + .id = 7, + .init = hdmi_init, + .dpcm_playback = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), + }, + { + .name = "iDisp4", + .id = 8, + .init = hdmi_init, + .dpcm_playback = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(idisp4_pin, idisp4_codec, platform), + }, +}; + +/* SoC card */ +static struct snd_soc_card snd_soc_card_ehl_rt5660 = { + .name = "ehl-rt5660", + .owner = THIS_MODULE, + .dai_link = ehl_rt5660_dailink, + .num_links = ARRAY_SIZE(ehl_rt5660_dailink), + .dapm_widgets = rt5660_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5660_widgets), + .dapm_routes = rt5660_map, + .num_dapm_routes = ARRAY_SIZE(rt5660_map), + .controls = rt5660_controls, + .num_controls = ARRAY_SIZE(rt5660_controls), + .fully_routed = true, + .late_probe = card_late_probe, +}; + +/* If hdmi codec is not supported, switch to use dummy codec */ +static void hdmi_link_init(struct snd_soc_card *card, + struct sof_card_private *ctx, + struct snd_soc_acpi_mach *mach) +{ + struct snd_soc_dai_link *link; + int i; + + if (mach->mach_params.common_hdmi_codec_drv && + (mach->mach_params.codec_mask & IDISP_CODEC_MASK)) { + ctx->idisp_codec = true; + return; + } + + /* + * if HDMI is not enabled in kernel config, or + * hdmi codec is not supported + */ + for (i = HDMI_LINK_START; i <= HDMI_LINE_END; i++) { + link = &card->dai_link[i]; + link->codecs[0].name = "snd-soc-dummy"; + link->codecs[0].dai_name = "snd-soc-dummy-dai"; + } +} + +static int snd_ehl_rt5660_probe(struct platform_device *pdev) +{ + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card = &snd_soc_card_ehl_rt5660; + struct sof_card_private *ctx; + int ret; + + card->dev = &pdev->dev; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); + snd_soc_card_set_drvdata(card, ctx); + + mach = pdev->dev.platform_data; + ret = snd_soc_fixup_dai_links_platform_name(card, + mach->mach_params.platform); + if (ret) + return ret; + + hdmi_link_init(card, ctx, mach); + + return devm_snd_soc_register_card(&pdev->dev, card); +} + +static const struct platform_device_id ehl_board_ids[] = { + { .name = "ehl_rt5660" }, + { } +}; + +static struct platform_driver snd_ehl_rt5660_driver = { + .driver = { + .name = "ehl_rt5660", + .pm = &snd_soc_pm_ops, + }, + .probe = snd_ehl_rt5660_probe, + .id_table = ehl_board_ids, +}; + +module_platform_driver(snd_ehl_rt5660_driver); + +MODULE_DESCRIPTION("ASoC Intel(R) Elkhartlake + rt5660 Machine driver"); +MODULE_AUTHOR("libin.yang@intel.com"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:ehl_rt5660"); diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c index a1290c3fa99f..b9ae0e2c959f 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -8,8 +8,15 @@ #include #include +#include "../skylake/skl.h" struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = { + { + .id = "INTC1027", + .drv_name = "ehl_rt5660", + .sof_fw_filename = "sof-ehl.ri", + .sof_tplg_filename = "sof-ehl-rt5660.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ehl_machines); From 5930d02c2d533aa9cbc2b55ad27b41802858da16 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 Apr 2020 13:58:20 -0500 Subject: [PATCH 017/428] ASoC: intel: sof_sdw: init all aggregated codecs Init codecs which belong to the same group id on all links. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200409185827.16255-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 41 ++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index a64dc563b47e..6a1b51c0546b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -411,25 +411,36 @@ static int create_codec_dai_name(struct device *dev, static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, - bool playback) + bool playback, int group_id) { int i; - for (i = 0; i < link->num_adr; i++) { - unsigned int part_id; - int codec_index; + do { + /* + * Initialize the codec. If codec is part of an aggregated + * group (group_id>0), initialize all codecs belonging to + * same group. + */ + for (i = 0; i < link->num_adr; i++) { + unsigned int part_id; + int codec_index; - part_id = SDW_PART_ID(link->adr_d[i].adr); - codec_index = find_codec_info_part(part_id); + part_id = SDW_PART_ID(link->adr_d[i].adr); + codec_index = find_codec_info_part(part_id); - if (codec_index < 0) - return codec_index; - - if (codec_info_list[codec_index].init) - codec_info_list[codec_index].init(link, dai_links, - &codec_info_list[codec_index], - playback); - } + if (codec_index < 0) + return codec_index; + /* The group_id is > 0 iff the codec is aggregated */ + if (link->adr_d[i].endpoints->group_id != group_id) + continue; + if (codec_info_list[codec_index].init) + codec_info_list[codec_index].init(link, + dai_links, + &codec_info_list[codec_index], + playback); + } + link++; + } while (link->mask && group_id); return 0; } @@ -623,7 +634,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index, NULL, &sdw_ops); ret = set_codec_init_func(link, dai_links + (*be_index)++, - playback); + playback, group_id); if (ret < 0) { dev_err(dev, "failed to init codec %d", codec_index); return ret; From 35e648cc66ac814ae1114695e6ace26bc63504c8 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 9 Apr 2020 13:58:21 -0500 Subject: [PATCH 018/428] ASoC: Intel: sof-da7219-max98373: add DMIC widget and route Add DMIC endpoint widget and route to make DMIC DAPM routes completed, to make DAPM Power Management works for DMIC streams. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200409185827.16255-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219_max98373.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index 8b5b74ba349f..8ca8f76470fa 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -86,6 +86,8 @@ static const struct snd_soc_dapm_widget widgets[] = { SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; static const struct snd_soc_dapm_route audio_map[] = { @@ -99,6 +101,9 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Left Spk", NULL, "Left BE_OUT" }, { "Right Spk", NULL, "Right BE_OUT" }, + + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, }; /* For MAX98360A amp */ @@ -111,6 +116,8 @@ static const struct snd_soc_dapm_widget max98360a_widgets[] = { SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; static const struct snd_soc_dapm_route max98360a_map[] = { @@ -123,6 +130,9 @@ static const struct snd_soc_dapm_route max98360a_map[] = { { "Headset Mic", NULL, "Platform Clock" }, {"Spk", NULL, "Speaker"}, + + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, }; static struct snd_soc_jack headset; From 272e68d06539d0abc39d949657a2bc6c5ee25647 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:58:22 -0500 Subject: [PATCH 019/428] ASoC: Intel: sof_sdw_hdmi: fix compilation issue in fallback mode Missing prefix causing build fail when NOCODEC option is selected Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200409185827.16255-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c index c7b5612a39e6..93e00b03cf85 100644 --- a/sound/soc/intel/boards/sof_sdw_hdmi.c +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -90,7 +90,7 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card) return hdac_hdmi_jack_port_init(component, &card->dapm); } #else -int hdmi_card_late_probe(struct snd_soc_card *card) +int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card) { return 0; } From 5611e6f4b32bbdfe973e22d1534c2838c57408b7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:58:23 -0500 Subject: [PATCH 020/428] ASoC: Intel: sof_sdw_hdmi: remove codec_dai use Use macro instead. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200409185827.16255-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c index 93e00b03cf85..cb1118e78e89 100644 --- a/sound/soc/intel/boards/sof_sdw_hdmi.c +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -28,7 +28,7 @@ struct hdmi_pcm { int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd) { struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); From 680ca80f731e11ff510f8ec2777f920ee228e54a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:58:24 -0500 Subject: [PATCH 021/428] ASoC: Intel: sof_sdw_rt1308: remove codec dai use Use macro. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200409185827.16255-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_rt1308.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c index 321768e54d08..a3d0e053b1a6 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -93,7 +93,7 @@ static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out; int err; From f11633da41bd00cc436e4e9b143bd6a00b9b65c6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:58:25 -0500 Subject: [PATCH 022/428] ASoC: Intel: sof_sdw_rt5682: remove codec_dai use Use macro. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200409185827.16255-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_rt5682.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index 5aa6211a1ed9..6680dde76682 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -47,7 +47,8 @@ static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; struct mc_private *ctx = snd_soc_card_get_drvdata(card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; struct snd_soc_jack *jack; int ret; From 6a739362211b14c1cfe56929c1da71f15c5e6143 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:58:26 -0500 Subject: [PATCH 023/428] ASoC: Intel: sof_sdw_rt700: remove codec_dai use Use macro Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200409185827.16255-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_rt700.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index 2ee4e6910d7f..d3725bb91e43 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -47,7 +47,8 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; struct mc_private *ctx = snd_soc_card_get_drvdata(card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; struct snd_soc_jack *jack; int ret; From 30e3edfbd1bf2f79287a5586508bb51f3fce5826 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 13:58:27 -0500 Subject: [PATCH 024/428] ASoC: Intel: sof_sdw_rt711: remove codec_dai use Use macro. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200409185827.16255-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_rt711.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 2a4917e3d561..8590a8a8889f 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -71,7 +71,8 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; struct mc_private *ctx = snd_soc_card_get_drvdata(card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; struct snd_soc_jack *jack; int ret; From 3ef9d5073b552d56bd6daf2af1e89b7e8d4df183 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 30 Mar 2020 23:40:11 +0300 Subject: [PATCH 025/428] ASoC: tegra: tegra_wm8903: Support nvidia, headset property The microphone-jack state needs to be masked in a case of a 4-pin jack when microphone and ground pins are shorted. Presence of nvidia,headset tells that WM8903 CODEC driver should mask microphone's status if short circuit is detected, i.e headphones are inserted. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20200330204011.18465-3-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 9b5651502f12..3aca354f9e08 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -177,6 +177,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_component *component = codec_dai->component; struct snd_soc_card *card = rtd->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); + int shrt = 0; if (gpio_is_valid(machine->gpio_hp_det)) { tegra_wm8903_hp_jack_gpio.gpio = machine->gpio_hp_det; @@ -189,12 +190,15 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) &tegra_wm8903_hp_jack_gpio); } + if (of_property_read_bool(card->dev->of_node, "nvidia,headset")) + shrt = SND_JACK_MICROPHONE; + snd_soc_card_jack_new(rtd->card, "Mic Jack", SND_JACK_MICROPHONE, &tegra_wm8903_mic_jack, tegra_wm8903_mic_jack_pins, ARRAY_SIZE(tegra_wm8903_mic_jack_pins)); wm8903_mic_detect(component, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE, - 0); + shrt); snd_soc_dapm_force_enable_pin(&card->dapm, "MICBIAS"); From 8240fe6c91b884b5f1f861a8c22721d6ea4c53c9 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 30 Mar 2020 23:40:10 +0300 Subject: [PATCH 026/428] ASoC: tegra-wm8903: Document new nvidia, headset property Some devices have a 4-pin headset jack instead of 3-pin microphone jack. The new boolean nvidia,headset property tells that the Mic Jack represents the state of a headset microphone. This additional hardware description is needed because microphone detection procedure differs in a case of a 4-pin jack from a 3-pin jack. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20200330204011.18465-2-digetx@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt index a8f2b0c56c79..bbd581a8c5bc 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt @@ -29,6 +29,7 @@ Optional properties: - nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in - nvidia,int-mic-en-gpios : The GPIO that enables the internal microphone - nvidia,ext-mic-en-gpios : The GPIO that enables the external microphone +- nvidia,headset : The Mic Jack represents state of the headset microphone pin Example: From e8ec193e485d933946ca7cc788c5503cd38af1a2 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Tue, 7 Apr 2020 16:29:29 +0800 Subject: [PATCH 027/428] ASoC: wm8994: remove wm1811_snd_controls and mixin_boost_tlv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following gcc warning: sound/soc/codecs/wm8994.c:736:38: warning: ‘wm1811_snd_controls’ defined but not used [-Wunused-const-variable=] static const struct snd_kcontrol_new wm1811_snd_controls[] = { ^~~~~~~~~~~~~~~~~~~ Reported-by: Hulk Robot Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200407082932.41511-2-yanaijie@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 15ce64a48a87..55d0b9be6ff0 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -285,7 +285,6 @@ static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); -static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0); #define WM8994_DRC_SWITCH(xname, reg, shift) \ SOC_SINGLE_EXT(xname, reg, shift, 1, 0, \ @@ -733,13 +732,6 @@ SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume", 7, 1, ng_tlv), }; -static const struct snd_kcontrol_new wm1811_snd_controls[] = { -SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0, - mixin_boost_tlv), -SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0, - mixin_boost_tlv), -}; - /* We run all mode setting through a function to enforce audio mode */ static void wm1811_jackdet_set_mode(struct snd_soc_component *component, u16 mode) { From cdab86902d07800a6393af1967fe8d343a27e526 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Tue, 7 Apr 2020 16:29:30 +0800 Subject: [PATCH 028/428] ASoC: wm8991: remove defined but not used 'wm8991_dapm_rxvoice_controls' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following gcc warning: sound/soc/codecs/wm8991.c:480:38: warning: ‘wm8991_dapm_rxvoice_controls’ defined but not used [-Wunused-const-variable=] static const struct snd_kcontrol_new wm8991_dapm_rxvoice_controls[] = { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ Reported-by: Hulk Robot Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200407082932.41511-3-yanaijie@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 93c156782d59..f8375d67e901 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -476,14 +476,6 @@ static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum, static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); -/* RXVOICE */ -static const struct snd_kcontrol_new wm8991_dapm_rxvoice_controls[] = { - SOC_DAPM_SINGLE_TLV("LIN4RXN", WM8991_INPUT_MIXER5, WM8991_LR4BVOL_SHIFT, - WM8991_LR4BVOL_MASK, 0, in_mix_tlv), - SOC_DAPM_SINGLE_TLV("RIN4RXP", WM8991_INPUT_MIXER6, WM8991_RL4BVOL_SHIFT, - WM8991_RL4BVOL_MASK, 0, in_mix_tlv), -}; - /* LOMIX */ static const struct snd_kcontrol_new wm8991_dapm_lomix_controls[] = { SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER1, From f840ebfe58027b43d6a6ba261c11cc80963952d6 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Tue, 7 Apr 2020 16:29:31 +0800 Subject: [PATCH 029/428] ASoC: wm8990: remove some defined but unused symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following gcc warning: sound/soc/codecs/wm8990.c:1309:35: warning: ‘wm8990_regmap’ defined but not used [-Wunused-const-variable=] static const struct regmap_config wm8990_regmap = { ^~~~~~~~~~~~~ sound/soc/codecs/wm8990.c:490:38: warning: ‘wm8990_dapm_rxvoice_controls’ defined but not used [-Wunused-const-variable=] static const struct snd_kcontrol_new wm8990_dapm_rxvoice_controls[] = { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sound/soc/codecs/wm8990.c:120:35: warning: ‘out_omix_tlv’ defined but not used [-Wunused-const-variable=] static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0); ^ sound/soc/codecs/wm8990.c:112:35: warning: ‘rec_mix_tlv’ defined but not used [-Wunused-const-variable=] static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0); ^ Reported-by: Hulk Robot Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200407082932.41511-4-yanaijie@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8990.c | 98 --------------------------------------- 1 file changed, 98 deletions(-) diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index cfe7892696dd..499a29b47d5e 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -32,93 +32,14 @@ struct wm8990_priv { unsigned int pcmclk; }; -static bool wm8990_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8990_RESET: - return true; - default: - return false; - } -} - -static const struct reg_default wm8990_reg_defaults[] = { - { 1, 0x0000 }, /* R1 - Power Management (1) */ - { 2, 0x6000 }, /* R2 - Power Management (2) */ - { 3, 0x0000 }, /* R3 - Power Management (3) */ - { 4, 0x4050 }, /* R4 - Audio Interface (1) */ - { 5, 0x4000 }, /* R5 - Audio Interface (2) */ - { 6, 0x01C8 }, /* R6 - Clocking (1) */ - { 7, 0x0000 }, /* R7 - Clocking (2) */ - { 8, 0x0040 }, /* R8 - Audio Interface (3) */ - { 9, 0x0040 }, /* R9 - Audio Interface (4) */ - { 10, 0x0004 }, /* R10 - DAC CTRL */ - { 11, 0x00C0 }, /* R11 - Left DAC Digital Volume */ - { 12, 0x00C0 }, /* R12 - Right DAC Digital Volume */ - { 13, 0x0000 }, /* R13 - Digital Side Tone */ - { 14, 0x0100 }, /* R14 - ADC CTRL */ - { 15, 0x00C0 }, /* R15 - Left ADC Digital Volume */ - { 16, 0x00C0 }, /* R16 - Right ADC Digital Volume */ - - { 18, 0x0000 }, /* R18 - GPIO CTRL 1 */ - { 19, 0x1000 }, /* R19 - GPIO1 & GPIO2 */ - { 20, 0x1010 }, /* R20 - GPIO3 & GPIO4 */ - { 21, 0x1010 }, /* R21 - GPIO5 & GPIO6 */ - { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */ - { 23, 0x0800 }, /* R23 - GPIO_POL */ - { 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */ - { 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */ - { 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */ - { 27, 0x008B }, /* R27 - Right Line Input 3&4 Volume */ - { 28, 0x0000 }, /* R28 - Left Output Volume */ - { 29, 0x0000 }, /* R29 - Right Output Volume */ - { 30, 0x0066 }, /* R30 - Line Outputs Volume */ - { 31, 0x0022 }, /* R31 - Out3/4 Volume */ - { 32, 0x0079 }, /* R32 - Left OPGA Volume */ - { 33, 0x0079 }, /* R33 - Right OPGA Volume */ - { 34, 0x0003 }, /* R34 - Speaker Volume */ - { 35, 0x0003 }, /* R35 - ClassD1 */ - - { 37, 0x0100 }, /* R37 - ClassD3 */ - { 38, 0x0079 }, /* R38 - ClassD4 */ - { 39, 0x0000 }, /* R39 - Input Mixer1 */ - { 40, 0x0000 }, /* R40 - Input Mixer2 */ - { 41, 0x0000 }, /* R41 - Input Mixer3 */ - { 42, 0x0000 }, /* R42 - Input Mixer4 */ - { 43, 0x0000 }, /* R43 - Input Mixer5 */ - { 44, 0x0000 }, /* R44 - Input Mixer6 */ - { 45, 0x0000 }, /* R45 - Output Mixer1 */ - { 46, 0x0000 }, /* R46 - Output Mixer2 */ - { 47, 0x0000 }, /* R47 - Output Mixer3 */ - { 48, 0x0000 }, /* R48 - Output Mixer4 */ - { 49, 0x0000 }, /* R49 - Output Mixer5 */ - { 50, 0x0000 }, /* R50 - Output Mixer6 */ - { 51, 0x0180 }, /* R51 - Out3/4 Mixer */ - { 52, 0x0000 }, /* R52 - Line Mixer1 */ - { 53, 0x0000 }, /* R53 - Line Mixer2 */ - { 54, 0x0000 }, /* R54 - Speaker Mixer */ - { 55, 0x0000 }, /* R55 - Additional Control */ - { 56, 0x0000 }, /* R56 - AntiPOP1 */ - { 57, 0x0000 }, /* R57 - AntiPOP2 */ - { 58, 0x0000 }, /* R58 - MICBIAS */ - - { 60, 0x0008 }, /* R60 - PLL1 */ - { 61, 0x0031 }, /* R61 - PLL2 */ - { 62, 0x0026 }, /* R62 - PLL3 */ -}; - #define wm8990_reset(c) snd_soc_component_write(c, WM8990_RESET, 0) -static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0); - static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0); static const DECLARE_TLV_DB_SCALE(out_mix_tlv, 0, -2100, 0); static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0); -static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0); - static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0); static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0); @@ -486,14 +407,6 @@ static SOC_ENUM_SINGLE_DECL(wm8990_ainrmux_enum, static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum); -/* RXVOICE */ -static const struct snd_kcontrol_new wm8990_dapm_rxvoice_controls[] = { -SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8990_INPUT_MIXER5, WM8990_LR4BVOL_SHIFT, - WM8990_LR4BVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8990_INPUT_MIXER6, WM8990_RL4BVOL_SHIFT, - WM8990_RL4BVOL_MASK, 0, in_mix_tlv), -}; - /* LOMIX */ static const struct snd_kcontrol_new wm8990_dapm_lomix_controls[] = { SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER1, @@ -1306,17 +1219,6 @@ static const struct snd_soc_component_driver soc_component_dev_wm8990 = { .non_legacy_dai_naming = 1, }; -static const struct regmap_config wm8990_regmap = { - .reg_bits = 8, - .val_bits = 16, - - .max_register = WM8990_PLL3, - .volatile_reg = wm8990_volatile_register, - .reg_defaults = wm8990_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8990_reg_defaults), - .cache_type = REGCACHE_RBTREE, -}; - static int wm8990_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { From 4c979a775432f8a1c9b6cfd9bf466eba05e96c9d Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Tue, 7 Apr 2020 16:29:32 +0800 Subject: [PATCH 030/428] ASoC: wm8900: remove some defined but not used symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following gcc warning: sound/soc/codecs/wm8900.c:449:38: warning: ‘wm8900_dapm_routput2_control’ defined but not used [-Wunused-const-variable=] static const struct snd_kcontrol_new wm8900_dapm_routput2_control = ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sound/soc/codecs/wm8900.c:446:38: warning: ‘wm8900_dapm_loutput2_control’ defined but not used [-Wunused-const-variable=] static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ Reported-by: Hulk Robot Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200407082932.41511-5-yanaijie@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8900.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 271235a69c01..3e239fa9bc8d 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -443,12 +443,6 @@ SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1, }; -static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = -SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); - -static const struct snd_kcontrol_new wm8900_dapm_routput2_control = -SOC_DAPM_SINGLE("LINEOUT2R Switch", WM8900_REG_POWER3, 5, 1, 0); - static const struct snd_kcontrol_new wm8900_loutmix_controls[] = { SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0), SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0), From 3e8f3bd047163d30fb1ad32ca7e4628921555c09 Mon Sep 17 00:00:00 2001 From: Thomas Ebeling Date: Tue, 14 Apr 2020 23:10:29 +0200 Subject: [PATCH 031/428] ALSA: usb-audio: RME Babyface Pro mixer patch Added mixer quirks to allow controlling the internal DSP of the RME Babyface Pro and its successor Babyface Pro FS. Signed-off-by: Thomas Ebeling Link: https://lore.kernel.org/r/20200414211019.qprg7whepg2y7nei@bollie.ca9.eu Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 418 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 418 insertions(+) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 02b036b2aefb..f0302ad7f5a0 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2181,6 +2181,421 @@ static int snd_rme_controls_create(struct usb_mixer_interface *mixer) return 0; } +/* + * RME Babyface Pro (FS) + * + * These devices exposes a couple of DSP functions via request to EP0. + * Switches are available via control registers, while routing is controlled + * by controlling the volume on each possible crossing point. + * Volume control is linear, from -inf (dec. 0) to +6dB (dec. 46341) with + * 0dB being at dec. 32768. + */ +enum { + SND_BBFPRO_CTL_REG1 = 0, + SND_BBFPRO_CTL_REG2 +}; + +#define SND_BBFPRO_CTL_REG_MASK 1 +#define SND_BBFPRO_CTL_IDX_MASK 0xff +#define SND_BBFPRO_CTL_IDX_SHIFT 1 +#define SND_BBFPRO_CTL_VAL_MASK 1 +#define SND_BBFPRO_CTL_VAL_SHIFT 9 +#define SND_BBFPRO_CTL_REG1_CLK_MASTER 0 +#define SND_BBFPRO_CTL_REG1_CLK_OPTICAL 1 +#define SND_BBFPRO_CTL_REG1_SPDIF_PRO 7 +#define SND_BBFPRO_CTL_REG1_SPDIF_EMPH 8 +#define SND_BBFPRO_CTL_REG1_SPDIF_OPTICAL 10 +#define SND_BBFPRO_CTL_REG2_48V_AN1 0 +#define SND_BBFPRO_CTL_REG2_48V_AN2 1 +#define SND_BBFPRO_CTL_REG2_SENS_IN3 2 +#define SND_BBFPRO_CTL_REG2_SENS_IN4 3 +#define SND_BBFPRO_CTL_REG2_PAD_AN1 4 +#define SND_BBFPRO_CTL_REG2_PAD_AN2 5 + +#define SND_BBFPRO_MIXER_IDX_MASK 0x1ff +#define SND_BBFPRO_MIXER_VAL_MASK 0x3ffff +#define SND_BBFPRO_MIXER_VAL_SHIFT 9 +#define SND_BBFPRO_MIXER_VAL_MIN 0 // -inf +#define SND_BBFPRO_MIXER_VAL_MAX 46341 // +6dB + +#define SND_BBFPRO_USBREQ_CTL_REG1 0x10 +#define SND_BBFPRO_USBREQ_CTL_REG2 0x17 +#define SND_BBFPRO_USBREQ_MIXER 0x12 + +static int snd_bbfpro_ctl_update(struct usb_mixer_interface *mixer, u8 reg, + u8 index, u8 value) +{ + int err; + u16 usb_req, usb_idx, usb_val; + struct snd_usb_audio *chip = mixer->chip; + + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; + + if (reg == SND_BBFPRO_CTL_REG1) { + usb_req = SND_BBFPRO_USBREQ_CTL_REG1; + if (index == SND_BBFPRO_CTL_REG1_CLK_OPTICAL) { + usb_idx = 3; + usb_val = value ? 3 : 0; + } else { + usb_idx = 1 << index; + usb_val = value ? usb_idx : 0; + } + } else { + usb_req = SND_BBFPRO_USBREQ_CTL_REG2; + usb_idx = 1 << index; + usb_val = value ? usb_idx : 0; + } + + err = snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), usb_req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + usb_val, usb_idx, 0, 0); + + snd_usb_unlock_shutdown(chip); + return err; +} + +static int snd_bbfpro_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u8 reg, idx, val; + int pv; + + pv = kcontrol->private_value; + reg = pv & SND_BBFPRO_CTL_REG_MASK; + idx = (pv >> SND_BBFPRO_CTL_IDX_SHIFT) & SND_BBFPRO_CTL_IDX_MASK; + val = kcontrol->private_value >> SND_BBFPRO_CTL_VAL_SHIFT; + + if ((reg == SND_BBFPRO_CTL_REG1 && + idx == SND_BBFPRO_CTL_REG1_CLK_OPTICAL) || + (reg == SND_BBFPRO_CTL_REG2 && + (idx == SND_BBFPRO_CTL_REG2_SENS_IN3 || + idx == SND_BBFPRO_CTL_REG2_SENS_IN4))) { + ucontrol->value.enumerated.item[0] = val; + } else { + ucontrol->value.integer.value[0] = val; + } + return 0; +} + +static int snd_bbfpro_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + u8 reg, idx; + int pv; + + pv = kcontrol->private_value; + reg = pv & SND_BBFPRO_CTL_REG_MASK; + idx = (pv >> SND_BBFPRO_CTL_IDX_SHIFT) & SND_BBFPRO_CTL_IDX_MASK; + + if (reg == SND_BBFPRO_CTL_REG1 && + idx == SND_BBFPRO_CTL_REG1_CLK_OPTICAL) { + static const char * const texts[2] = { + "AutoSync", + "Internal" + }; + return snd_ctl_enum_info(uinfo, 1, 2, texts); + } else if (reg == SND_BBFPRO_CTL_REG2 && + (idx == SND_BBFPRO_CTL_REG2_SENS_IN3 || + idx == SND_BBFPRO_CTL_REG2_SENS_IN4)) { + static const char * const texts[2] = { + "-10dBV", + "+4dBu" + }; + return snd_ctl_enum_info(uinfo, 1, 2, texts); + } + + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + return 0; +} + +static int snd_bbfpro_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int err; + u8 reg, idx; + int old_value, pv, val; + + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); + struct usb_mixer_interface *mixer = list->mixer; + + pv = kcontrol->private_value; + reg = pv & SND_BBFPRO_CTL_REG_MASK; + idx = (pv >> SND_BBFPRO_CTL_IDX_SHIFT) & SND_BBFPRO_CTL_IDX_MASK; + old_value = (pv >> SND_BBFPRO_CTL_VAL_SHIFT) & SND_BBFPRO_CTL_VAL_MASK; + + if ((reg == SND_BBFPRO_CTL_REG1 && + idx == SND_BBFPRO_CTL_REG1_CLK_OPTICAL) || + (reg == SND_BBFPRO_CTL_REG2 && + (idx == SND_BBFPRO_CTL_REG2_SENS_IN3 || + idx == SND_BBFPRO_CTL_REG2_SENS_IN4))) { + val = ucontrol->value.enumerated.item[0]; + } else { + val = ucontrol->value.integer.value[0]; + } + + if (val > 1) + return -EINVAL; + + if (val == old_value) + return 0; + + kcontrol->private_value = reg + | ((idx & SND_BBFPRO_CTL_IDX_MASK) << SND_BBFPRO_CTL_IDX_SHIFT) + | ((val & SND_BBFPRO_CTL_VAL_MASK) << SND_BBFPRO_CTL_VAL_SHIFT); + + err = snd_bbfpro_ctl_update(mixer, reg, idx, val); + return err < 0 ? err : 1; +} + +static int snd_bbfpro_ctl_resume(struct usb_mixer_elem_list *list) +{ + u8 reg, idx; + int value, pv; + + pv = list->kctl->private_value; + reg = pv & SND_BBFPRO_CTL_REG_MASK; + idx = (pv >> SND_BBFPRO_CTL_IDX_SHIFT) & SND_BBFPRO_CTL_IDX_MASK; + value = (pv >> SND_BBFPRO_CTL_VAL_SHIFT) & SND_BBFPRO_CTL_VAL_MASK; + + return snd_bbfpro_ctl_update(list->mixer, reg, idx, value); +} + +static int snd_bbfpro_vol_update(struct usb_mixer_interface *mixer, u16 index, + u32 value) +{ + struct snd_usb_audio *chip = mixer->chip; + int err; + u16 idx; + u16 usb_idx, usb_val; + u32 v; + + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; + + idx = index & SND_BBFPRO_MIXER_IDX_MASK; + // 18 bit linear volume, split so 2 bits end up in index. + v = value & SND_BBFPRO_MIXER_VAL_MASK; + usb_idx = idx | (v & 0x3) << 14; + usb_val = (v >> 2) & 0xffff; + + err = snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), + SND_BBFPRO_USBREQ_MIXER, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, + usb_val, usb_idx, 0, 0); + + snd_usb_unlock_shutdown(chip); + return err; +} + +static int snd_bbfpro_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = + kcontrol->private_value >> SND_BBFPRO_MIXER_VAL_SHIFT; + return 0; +} + +static int snd_bbfpro_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = SND_BBFPRO_MIXER_VAL_MIN; + uinfo->value.integer.max = SND_BBFPRO_MIXER_VAL_MAX; + return 0; +} + +static int snd_bbfpro_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int err; + u16 idx; + u32 new_val, old_value, uvalue; + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); + struct usb_mixer_interface *mixer = list->mixer; + + uvalue = ucontrol->value.integer.value[0]; + idx = kcontrol->private_value & SND_BBFPRO_MIXER_IDX_MASK; + old_value = kcontrol->private_value >> SND_BBFPRO_MIXER_VAL_SHIFT; + + if (uvalue > SND_BBFPRO_MIXER_VAL_MAX) + return -EINVAL; + + if (uvalue == old_value) + return 0; + + new_val = uvalue & SND_BBFPRO_MIXER_VAL_MASK; + + kcontrol->private_value = idx + | (new_val << SND_BBFPRO_MIXER_VAL_SHIFT); + + err = snd_bbfpro_vol_update(mixer, idx, new_val); + return err < 0 ? err : 1; +} + +static int snd_bbfpro_vol_resume(struct usb_mixer_elem_list *list) +{ + int pv = list->kctl->private_value; + u16 idx = pv & SND_BBFPRO_MIXER_IDX_MASK; + u32 val = (pv >> SND_BBFPRO_MIXER_VAL_SHIFT) + & SND_BBFPRO_MIXER_VAL_MASK; + return snd_bbfpro_vol_update(list->mixer, idx, val); +} + +// Predfine elements +static const struct snd_kcontrol_new snd_bbfpro_ctl_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .index = 0, + .info = snd_bbfpro_ctl_info, + .get = snd_bbfpro_ctl_get, + .put = snd_bbfpro_ctl_put +}; + +static const struct snd_kcontrol_new snd_bbfpro_vol_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .index = 0, + .info = snd_bbfpro_vol_info, + .get = snd_bbfpro_vol_get, + .put = snd_bbfpro_vol_put +}; + +static int snd_bbfpro_ctl_add(struct usb_mixer_interface *mixer, u8 reg, + u8 index, char *name) +{ + struct snd_kcontrol_new knew = snd_bbfpro_ctl_control; + + knew.name = name; + knew.private_value = (reg & SND_BBFPRO_CTL_REG_MASK) + | ((index & SND_BBFPRO_CTL_IDX_MASK) + << SND_BBFPRO_CTL_IDX_SHIFT); + + return add_single_ctl_with_resume(mixer, 0, snd_bbfpro_ctl_resume, + &knew, NULL); +} + +static int snd_bbfpro_vol_add(struct usb_mixer_interface *mixer, u16 index, + char *name) +{ + struct snd_kcontrol_new knew = snd_bbfpro_vol_control; + + knew.name = name; + knew.private_value = index & SND_BBFPRO_MIXER_IDX_MASK; + + return add_single_ctl_with_resume(mixer, 0, snd_bbfpro_vol_resume, + &knew, NULL); +} + +static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) +{ + int err, i, o; + char name[48]; + + static const char * const input[] = { + "AN1", "AN2", "IN3", "IN4", "AS1", "AS2", "ADAT3", + "ADAT4", "ADAT5", "ADAT6", "ADAT7", "ADAT8"}; + + static const char * const output[] = { + "AN1", "AN2", "PH3", "PH4", "AS1", "AS2", "ADAT3", "ADAT4", + "ADAT5", "ADAT6", "ADAT7", "ADAT8"}; + + for (o = 0 ; o < 12 ; ++o) { + for (i = 0 ; i < 12 ; ++i) { + // Line routing + snprintf(name, sizeof(name), + "%s-%s-%s Playback Volume", + (i < 2 ? "Mic" : "Line"), + input[i], output[o]); + err = snd_bbfpro_vol_add(mixer, (26 * o + i), name); + if (err < 0) + return err; + + // PCM routing... yes, it is output remapping + snprintf(name, sizeof(name), + "PCM-%s-%s Playback Volume", + output[i], output[o]); + err = snd_bbfpro_vol_add(mixer, (26 * o + 12 + i), + name); + if (err < 0) + return err; + } + } + + // Control Reg 1 + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, + SND_BBFPRO_CTL_REG1_CLK_OPTICAL, + "Sample Clock Source"); + if (err < 0) + return err; + + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, + SND_BBFPRO_CTL_REG1_SPDIF_PRO, + "IEC958 Pro Mask"); + if (err < 0) + return err; + + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, + SND_BBFPRO_CTL_REG1_SPDIF_EMPH, + "IEC958 Emphasis"); + if (err < 0) + return err; + + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, + SND_BBFPRO_CTL_REG1_SPDIF_OPTICAL, + "IEC958 Switch"); + if (err < 0) + return err; + + // Control Reg 2 + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, + SND_BBFPRO_CTL_REG2_48V_AN1, + "Mic-AN1 48V"); + if (err < 0) + return err; + + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, + SND_BBFPRO_CTL_REG2_48V_AN2, + "Mic-AN2 48V"); + if (err < 0) + return err; + + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, + SND_BBFPRO_CTL_REG2_SENS_IN3, + "Line-IN3 Sens."); + if (err < 0) + return err; + + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, + SND_BBFPRO_CTL_REG2_SENS_IN4, + "Line-IN4 Sens."); + if (err < 0) + return err; + + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, + SND_BBFPRO_CTL_REG2_PAD_AN1, + "Mic-AN1 PAD"); + if (err < 0) + return err; + + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, + SND_BBFPRO_CTL_REG2_PAD_AN2, + "Mic-AN2 PAD"); + if (err < 0) + return err; + + return 0; +} + int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) { int err = 0; @@ -2282,6 +2697,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x0194f, 0x010c): /* Presonus Studio 1810c */ err = snd_sc1810_init_mixer(mixer); break; + case USB_ID(0x2a39, 0x3fb0): /* RME Babyface Pro FS */ + err = snd_bbfpro_controls_create(mixer); + break; } return err; From 46b7e2ff8cb67f9f23bdfec0d8d08d803eb1146e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Apr 2020 22:26:47 -0500 Subject: [PATCH 032/428] ASoC: Intel: skl_hda_generic: remove rtd->codec_dai Use macro and solve compilation issues Reported-by: Stephen Rothwell Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200415032647.11209-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 64197b010e7d..35f222ed9912 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -175,7 +175,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card) struct snd_soc_pcm_runtime *rtd = list_first_entry(&card->rtd_list, struct snd_soc_pcm_runtime, list); - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_hda_priv *hda_pvt; if (!codec_dai) From 83b35f4586e235bfb785a7947b555ad8f3d96887 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Wed, 15 Apr 2020 12:45:13 +0800 Subject: [PATCH 033/428] ASoC: fsl_micfil: Omit superfluous error message in fsl_micfil_probe() In the function fsl_micfil_probe(), when get irq failed, the function platform_get_irq() logs an error message, so remove redundant message here. Signed-off-by: Tang Bin Signed-off-by: Shengju Zhang Link: https://lore.kernel.org/r/20200415044513.17492-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index f7f2d29f1bfe..e73bd6570a08 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -702,10 +702,8 @@ static int fsl_micfil_probe(struct platform_device *pdev) for (i = 0; i < MICFIL_IRQ_LINES; i++) { micfil->irq[i] = platform_get_irq(pdev, i); dev_err(&pdev->dev, "GET IRQ: %d\n", micfil->irq[i]); - if (micfil->irq[i] < 0) { - dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); + if (micfil->irq[i] < 0) return micfil->irq[i]; - } } if (of_property_read_bool(np, "fsl,shared-interrupt")) From 980f91778a2f4dcca43d16b7a83feda8df5c96e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Wed, 15 Apr 2020 12:24:34 -0400 Subject: [PATCH 034/428] ASoC: topology: Remove unneeded semicolon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is unnecessary semicolon after last bracket of if statement, remove it. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Link: https://lore.kernel.org/r/20200415162435.31859-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 33e8d189ba2f..a5cd73742dc5 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -2390,7 +2390,7 @@ static int soc_tplg_link_elems_load(struct soc_tplg *tplg, tplg->pos += le32_to_cpu(hdr->size) + le32_to_cpu(hdr->payload_size); return 0; - }; + } /* check the element size and count */ link = (struct snd_soc_tplg_link_config *)tplg->pos; From fe17e6cdc0fefca96ba9659be4b2b07487cbf0c5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 9 Apr 2020 10:18:28 +0300 Subject: [PATCH 035/428] ASoC: SOF: imx8: Fix randbuild error when do randconfig like this: CONFIG_SND_SOC_SOF_IMX8_SUPPORT=y CONFIG_SND_SOC_SOF_IMX8=y CONFIG_SND_SOC_SOF_OF=y CONFIG_IMX_DSP=m CONFIG_IMX_SCU=y there is a link error: sound/soc/sof/imx/imx8.o: In function 'imx8_send_msg': imx8.c:(.text+0x380): undefined reference to 'imx_dsp_ring_doorbell' Select IMX_DSP in SND_SOC_SOF_IMX8_SUPPORT to fix this Fixes: f9ad75468453 ("ASoC: SOF: imx: fix reverse CONFIG_SND_SOC_SOF_OF dependency") Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20200409071832.2039-2-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index bae4f7bf5f75..812749064ca8 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -14,7 +14,7 @@ if SND_SOC_SOF_IMX_TOPLEVEL config SND_SOC_SOF_IMX8_SUPPORT bool "SOF support for i.MX8" depends on IMX_SCU - depends on IMX_DSP + select IMX_DSP help This adds support for Sound Open Firmware for NXP i.MX8 platforms Say Y if you have such a device. From cb0312f61c3e95c71ec8955a94d42bf7eb5ba617 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 9 Apr 2020 10:18:29 +0300 Subject: [PATCH 036/428] ASoC: SOF: imx: fix undefined reference issue make.cross ARCH=mips allyesconfig fails with the following error: sound/soc/sof/sof-of-dev.o:(.data.sof_of_imx8qxp_desc+0x40): undefined reference to `sof_imx8x_ops'. This seems to be a Makefile order issue, solve by using the same structure as for Intel platforms. Fixes: f9ad75468453 ("ASoC: SOF: imx: fix reverse CONFIG_SND_SOC_SOF_OF dependency") Signed-off-by: Pierre-Louis Bossart Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20200409071832.2039-3-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 812749064ca8..9586635cf8ab 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -11,17 +11,26 @@ config SND_SOC_SOF_IMX_TOPLEVEL if SND_SOC_SOF_IMX_TOPLEVEL +config SND_SOC_SOF_IMX_OF + def_tristate SND_SOC_SOF_OF + select SND_SOC_SOF_IMX8 if SND_SOC_SOF_IMX8_SUPPORT + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level + config SND_SOC_SOF_IMX8_SUPPORT bool "SOF support for i.MX8" - depends on IMX_SCU - select IMX_DSP help This adds support for Sound Open Firmware for NXP i.MX8 platforms Say Y if you have such a device. If unsure select "N". config SND_SOC_SOF_IMX8 - def_tristate SND_SOC_SOF_OF - depends on SND_SOC_SOF_IMX8_SUPPORT + tristate + depends on IMX_SCU + select IMX_DSP + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level endif ## SND_SOC_SOF_IMX_IMX_TOPLEVEL From afb93d716533ddef20fc70e626f7b43f204cb411 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 9 Apr 2020 10:18:30 +0300 Subject: [PATCH 037/428] ASoC: SOF: imx: Add i.MX8M HW support This adds skeleton support for the audio DSP hardware found on NXP i.MX8M platform. There is one notable difference between i.MX8M and i.MX8, which doesn't allow us to reuse HW support from imx8.c file designed for i.MX8: On i.MX8M resources (clocks, power, pinctrl, etc) are managed by the Linux kernel while on i.MX8 resources are managed by a separate System Controller Firmware. This makes the interface to those resources completely different. Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20200409071832.2039-4-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 15 ++ sound/soc/sof/imx/Makefile | 2 + sound/soc/sof/imx/imx8m.c | 279 +++++++++++++++++++++++++++++++++++++ 3 files changed, 296 insertions(+) create mode 100644 sound/soc/sof/imx/imx8m.c diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 9586635cf8ab..0e7964bf4448 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -14,6 +14,7 @@ if SND_SOC_SOF_IMX_TOPLEVEL config SND_SOC_SOF_IMX_OF def_tristate SND_SOC_SOF_OF select SND_SOC_SOF_IMX8 if SND_SOC_SOF_IMX8_SUPPORT + select SND_SOC_SOF_IMX8M if SND_SOC_SOF_IMX8M_SUPPORT help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -33,4 +34,18 @@ config SND_SOC_SOF_IMX8 This option is not user-selectable but automagically handled by 'select' statements at a higher level +config SND_SOC_SOF_IMX8M_SUPPORT + bool "SOF support for i.MX8M" + help + This adds support for Sound Open Firmware for NXP i.MX8M platforms + Say Y if you have such a device. + If unsure select "N". + +config SND_SOC_SOF_IMX8M + tristate + depends on IMX_DSP + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level + endif ## SND_SOC_SOF_IMX_IMX_TOPLEVEL diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile index 6ef908e8c807..d9d8dc1765b8 100644 --- a/sound/soc/sof/imx/Makefile +++ b/sound/soc/sof/imx/Makefile @@ -1,4 +1,6 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) snd-sof-imx8-objs := imx8.o +snd-sof-imx8m-objs := imx8m.o obj-$(CONFIG_SND_SOC_SOF_IMX8) += snd-sof-imx8.o +obj-$(CONFIG_SND_SOC_SOF_IMX8M) += snd-sof-imx8m.o diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c new file mode 100644 index 000000000000..07451ba4efae --- /dev/null +++ b/sound/soc/sof/imx/imx8m.c @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// Copyright 2020 NXP +// +// Author: Daniel Baluta +// +// Hardware interface for audio DSP on i.MX8M + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../ops.h" + +#define MBOX_OFFSET 0x800000 +#define MBOX_SIZE 0x1000 + +struct imx8m_priv { + struct device *dev; + struct snd_sof_dev *sdev; + + /* DSP IPC handler */ + struct imx_dsp_ipc *dsp_ipc; + struct platform_device *ipc_dev; +}; + +static void imx8m_get_reply(struct snd_sof_dev *sdev) +{ + struct snd_sof_ipc_msg *msg = sdev->msg; + struct sof_ipc_reply reply; + int ret = 0; + + if (!msg) { + dev_warn(sdev->dev, "unexpected ipc interrupt\n"); + return; + } + + /* get reply */ + sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); + + if (reply.error < 0) { + memcpy(msg->reply_data, &reply, sizeof(reply)); + ret = reply.error; + } else { + /* reply has correct size? */ + if (reply.hdr.size != msg->reply_size) { + dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", + msg->reply_size, reply.hdr.size); + ret = -EINVAL; + } + + /* read the message */ + if (msg->reply_size > 0) + sof_mailbox_read(sdev, sdev->host_box.offset, + msg->reply_data, msg->reply_size); + } + + msg->reply_error = ret; +} + +static int imx8m_get_mailbox_offset(struct snd_sof_dev *sdev) +{ + return MBOX_OFFSET; +} + +static int imx8m_get_window_offset(struct snd_sof_dev *sdev, u32 id) +{ + return MBOX_OFFSET; +} + +static void imx8m_dsp_handle_reply(struct imx_dsp_ipc *ipc) +{ + struct imx8m_priv *priv = imx_dsp_get_data(ipc); + unsigned long flags; + + spin_lock_irqsave(&priv->sdev->ipc_lock, flags); + imx8m_get_reply(priv->sdev); + snd_sof_ipc_reply(priv->sdev, 0); + spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); +} + +static void imx8m_dsp_handle_request(struct imx_dsp_ipc *ipc) +{ + struct imx8m_priv *priv = imx_dsp_get_data(ipc); + + snd_sof_ipc_msgs_rx(priv->sdev); +} + +struct imx_dsp_ops imx8m_dsp_ops = { + .handle_reply = imx8m_dsp_handle_reply, + .handle_request = imx8m_dsp_handle_request, +}; + +static int imx8m_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) +{ + struct imx8m_priv *priv = (struct imx8m_priv *)sdev->private; + + sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, + msg->msg_size); + imx_dsp_ring_doorbell(priv->dsp_ipc, 0); + + return 0; +} + +/* + * DSP control. + */ +static int imx8m_run(struct snd_sof_dev *sdev) +{ + /* TODO: start DSP using Audio MIX bits */ + return 0; +} + +static int imx8m_probe(struct snd_sof_dev *sdev) +{ + struct platform_device *pdev = + container_of(sdev->dev, struct platform_device, dev); + struct device_node *np = pdev->dev.of_node; + struct device_node *res_node; + struct resource *mmio; + struct imx8m_priv *priv; + struct resource res; + u32 base, size; + int ret = 0; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + sdev->private = priv; + priv->dev = sdev->dev; + priv->sdev = sdev; + + priv->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", + PLATFORM_DEVID_NONE, + pdev, sizeof(*pdev)); + if (IS_ERR(priv->ipc_dev)) + return PTR_ERR(priv->ipc_dev); + + priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev); + if (!priv->dsp_ipc) { + /* DSP IPC driver not probed yet, try later */ + ret = -EPROBE_DEFER; + dev_err(sdev->dev, "Failed to get drvdata\n"); + goto exit_pdev_unregister; + } + + imx_dsp_set_data(priv->dsp_ipc, priv); + priv->dsp_ipc->ops = &imx8m_dsp_ops; + + /* DSP base */ + mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (mmio) { + base = mmio->start; + size = resource_size(mmio); + } else { + dev_err(sdev->dev, "error: failed to get DSP base at idx 0\n"); + ret = -EINVAL; + goto exit_pdev_unregister; + } + + sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size); + if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) { + dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n", + base, size); + ret = -ENODEV; + goto exit_pdev_unregister; + } + sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM; + + res_node = of_parse_phandle(np, "memory-region", 0); + if (!res_node) { + dev_err(&pdev->dev, "failed to get memory region node\n"); + ret = -ENODEV; + goto exit_pdev_unregister; + } + + ret = of_address_to_resource(res_node, 0, &res); + if (ret) { + dev_err(&pdev->dev, "failed to get reserved region address\n"); + goto exit_pdev_unregister; + } + + sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, + res.end - res.start + + 1); + if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { + dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", + base, size); + ret = -ENOMEM; + goto exit_pdev_unregister; + } + sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; + + /* set default mailbox offset for FW ready message */ + sdev->dsp_box.offset = MBOX_OFFSET; + + return 0; + +exit_pdev_unregister: + platform_device_unregister(priv->ipc_dev); + return ret; +} + +static int imx8m_remove(struct snd_sof_dev *sdev) +{ + struct imx8m_priv *priv = (struct imx8m_priv *)sdev->private; + + platform_device_unregister(priv->ipc_dev); + + return 0; +} + +/* on i.MX8 there is 1 to 1 match between type and BAR idx */ +static int imx8m_get_bar_index(struct snd_sof_dev *sdev, u32 type) +{ + return type; +} + +static void imx8m_ipc_msg_data(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream, + void *p, size_t sz) +{ + sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); +} + +static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream, + const struct sof_ipc_pcm_params_reply *reply) +{ + return 0; +} + +static struct snd_soc_dai_driver imx8m_dai[] = { +{ + .name = "sai-port", +}, +}; + +/* i.MX8 ops */ +struct snd_sof_dsp_ops sof_imx8m_ops = { + /* probe and remove */ + .probe = imx8m_probe, + .remove = imx8m_remove, + /* DSP core boot */ + .run = imx8m_run, + + /* Block IO */ + .block_read = sof_block_read, + .block_write = sof_block_write, + + /* ipc */ + .send_msg = imx8m_send_msg, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = imx8m_get_mailbox_offset, + .get_window_offset = imx8m_get_window_offset, + + .ipc_msg_data = imx8m_ipc_msg_data, + .ipc_pcm_params = imx8m_ipc_pcm_params, + + /* module loading */ + .load_module = snd_sof_parse_module_memcpy, + .get_bar_index = imx8m_get_bar_index, + /* firmware loading */ + .load_firmware = snd_sof_load_firmware_memcpy, + + /* DAI drivers */ + .drv = imx8m_dai, + .num_drv = 1, /* we have only 1 SAI interface on i.MX8M */ +}; +EXPORT_SYMBOL(sof_imx8m_ops); + +MODULE_LICENSE("Dual BSD/GPL"); From 58825cc2253986ec3a4d0d67b8b4dc30945afb52 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 9 Apr 2020 10:18:31 +0300 Subject: [PATCH 038/428] ASoC: SOF: Add i.MX8MP device descriptor Add SOF device and DT descriptor for i.MX8MP platform. Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20200409071832.2039-5-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-of-dev.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 16e49f2ee629..c6167597d6fe 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -14,6 +14,7 @@ extern struct snd_sof_dsp_ops sof_imx8_ops; extern struct snd_sof_dsp_ops sof_imx8x_ops; +extern struct snd_sof_dsp_ops sof_imx8m_ops; /* platform specific devices */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) @@ -34,6 +35,16 @@ static struct sof_dev_desc sof_of_imx8qm_desc = { }; #endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8M) +static struct sof_dev_desc sof_of_imx8mp_desc = { + .default_fw_path = "imx/sof", + .default_tplg_path = "imx/sof-tplg", + .default_fw_filename = "sof-imx8m.ri", + .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", + .ops = &sof_imx8m_ops, +}; +#endif + static const struct dev_pm_ops sof_of_pm = { SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, @@ -113,6 +124,9 @@ static const struct of_device_id sof_of_ids[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc}, { .compatible = "fsl,imx8qm-dsp", .data = &sof_of_imx8qm_desc}, +#endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8M) + { .compatible = "fsl,imx8mp-dsp", .data = &sof_of_imx8mp_desc}, #endif { } }; From 35a0f242520520dfa1e8eaf66f20d297b12e413e Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 9 Apr 2020 10:18:32 +0300 Subject: [PATCH 039/428] dt-bindings: dsp: fsl: Add fsl,imx8mp-dsp entry Minimal implementation needs the same DT properties as existing compatible strings. So, we just add the new compatible string in the list. Signed-off-by: Daniel Baluta Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200409071832.2039-6-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/dsp/fsl,dsp.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml index f04870d84542..65d4d07e1952 100644 --- a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml +++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml @@ -17,6 +17,8 @@ properties: compatible: enum: - fsl,imx8qxp-dsp + - fsl,imx8qm-dsp + - fsl,imx8mp-dsp reg: description: Should contain register location and length From 101001652ee7231bb02a8aa75d25fadb1c078c2c Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 15 Apr 2020 15:27:53 -0500 Subject: [PATCH 040/428] ASoC: SOF: topology: fix: handle DAI widget connections properly with multiple CPU DAI's Currently, when connecting a DAI widget to the BE CPU DAI, we overwrite the previous connections. This worked because we only ever had 1 CPU DAI for each rtd until now. But with multiple CPU DAI's, a new connection between a BE CPU DAI and the DAI widget should be established without affecting the previous connections. So, modify the loop to set the playback/capture widget for the first BE CPU DAI that does not have a connection established previously. Fixes: 4a7e26a4d833 ("ASoC: SOF: topology: connect dai widget to all cpu-dais") Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index fe8ba3e05e08..3386886fd743 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1257,15 +1257,45 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp, switch (w->id) { case snd_soc_dapm_dai_out: - for_each_rtd_cpu_dais(rtd, i, cpu_dai) - cpu_dai->capture_widget = w; + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + /* + * Please create DAI widget in the right order + * to ensure BE will connect to the right DAI + * widget. + */ + if (!cpu_dai->capture_widget) { + cpu_dai->capture_widget = w; + break; + } + } + if (i == rtd->num_cpus) { + dev_err(scomp->dev, "error: can't find BE for DAI %s\n", + w->name); + + return -EINVAL; + } dai->name = rtd->dai_link->name; dev_dbg(scomp->dev, "tplg: connected widget %s -> DAI link %s\n", w->name, rtd->dai_link->name); break; case snd_soc_dapm_dai_in: - for_each_rtd_cpu_dais(rtd, i, cpu_dai) - cpu_dai->playback_widget = w; + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + /* + * Please create DAI widget in the right order + * to ensure BE will connect to the right DAI + * widget. + */ + if (!cpu_dai->playback_widget) { + cpu_dai->playback_widget = w; + break; + } + } + if (i == rtd->num_cpus) { + dev_err(scomp->dev, "error: can't find BE for DAI %s\n", + w->name); + + return -EINVAL; + } dai->name = rtd->dai_link->name; dev_dbg(scomp->dev, "tplg: connected widget %s -> DAI link %s\n", w->name, rtd->dai_link->name); From 0730c0928d8941327f38dd72e53f9bdb0cc29e00 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:54 -0500 Subject: [PATCH 041/428] ASoC: SOF: Mark get_ext* function ext_hdr arguments as const This pointer can be mark as const to indicate that it is read only pointer. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 64af08293daa..312f7fffcb2c 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -15,9 +15,9 @@ #include "ops.h" static int get_ext_windows(struct snd_sof_dev *sdev, - struct sof_ipc_ext_data_hdr *ext_hdr) + const struct sof_ipc_ext_data_hdr *ext_hdr) { - struct sof_ipc_window *w = + const struct sof_ipc_window *w = container_of(ext_hdr, struct sof_ipc_window, ext_hdr); if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) @@ -33,11 +33,11 @@ static int get_ext_windows(struct snd_sof_dev *sdev, } static int get_cc_info(struct snd_sof_dev *sdev, - struct sof_ipc_ext_data_hdr *ext_hdr) + const struct sof_ipc_ext_data_hdr *ext_hdr) { int ret; - struct sof_ipc_cc_version *cc = + const struct sof_ipc_cc_version *cc = container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", From 92be17a559a8872b655512b1cf9d0bc407bace33 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:55 -0500 Subject: [PATCH 042/428] ASoC: SOF: Introduce offset in firmware data It makes possible to provide extra information to host before downloading firmware. Extra data should be put at the beginning of firmware binary. Exchange is done without any effort on DSP side. This mechanism will be used in extended manifest. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 3 +++ sound/soc/sof/intel/hda-loader.c | 9 +++++++-- sound/soc/sof/loader.c | 29 +++++++++++++++++++---------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/include/sound/sof.h b/include/sound/sof.h index a0cbca021230..969f554b0b7d 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -27,6 +27,9 @@ struct snd_sof_pdata { struct device *dev; + /* indicate how many first bytes shouldn't be loaded into DSP memory. */ + size_t fw_offset; + /* * notification callback used if the hardware initialization * can take time or is handled in a workqueue. This callback diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index e1550ccd0a49..1beaaf5879e2 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -293,8 +293,13 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) chip_info = desc->chip_info; - stripped_firmware.data = plat_data->fw->data; - stripped_firmware.size = plat_data->fw->size; + if (plat_data->fw->size < plat_data->fw_offset) { + dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n"); + return -EINVAL; + } + + stripped_firmware.data = plat_data->fw->data + plat_data->fw_offset; + stripped_firmware.size = plat_data->fw->size - plat_data->fw_offset; /* init for booting wait */ init_waitqueue_head(&sdev->boot_wait); diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 312f7fffcb2c..89f35db2577d 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -379,12 +379,19 @@ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, } EXPORT_SYMBOL(snd_sof_parse_module_memcpy); -static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw) +static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw, + size_t fw_offset) { struct snd_sof_fw_header *header; + size_t fw_size = fw->size - fw_offset; + + if (fw->size < fw_offset) { + dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n"); + return -EINVAL; + } /* Read the header information from the data pointer */ - header = (struct snd_sof_fw_header *)fw->data; + header = (struct snd_sof_fw_header *)(fw->data + fw_offset); /* verify FW sig */ if (strncmp(header->sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE) != 0) { @@ -393,9 +400,9 @@ static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw) } /* check size is valid */ - if (fw->size != header->file_size + sizeof(*header)) { + if (fw_size != header->file_size + sizeof(*header)) { dev_err(sdev->dev, "error: invalid filesize mismatch got 0x%zx expected 0x%zx\n", - fw->size, header->file_size + sizeof(*header)); + fw_size, header->file_size + sizeof(*header)); return -EINVAL; } @@ -406,7 +413,8 @@ static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw) return 0; } -static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw) +static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw, + size_t fw_offset) { struct snd_sof_fw_header *header; struct snd_sof_mod_hdr *module; @@ -415,14 +423,15 @@ static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw) int ret, count; size_t remaining; - header = (struct snd_sof_fw_header *)fw->data; + header = (struct snd_sof_fw_header *)(fw->data + fw_offset); load_module = sof_ops(sdev)->load_module; if (!load_module) return -EINVAL; /* parse each module */ - module = (struct snd_sof_mod_hdr *)((u8 *)(fw->data) + sizeof(*header)); - remaining = fw->size - sizeof(*header); + module = (struct snd_sof_mod_hdr *)(fw->data + fw_offset + + sizeof(*header)); + remaining = fw->size - sizeof(*header) - fw_offset; /* check for wrap */ if (remaining > fw->size) { dev_err(sdev->dev, "error: fw size smaller than header size\n"); @@ -502,7 +511,7 @@ int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev) return ret; /* make sure the FW header and file is valid */ - ret = check_header(sdev, plat_data->fw); + ret = check_header(sdev, plat_data->fw, plat_data->fw_offset); if (ret < 0) { dev_err(sdev->dev, "error: invalid FW header\n"); goto error; @@ -516,7 +525,7 @@ int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev) } /* parse and load firmware modules to DSP */ - ret = load_modules(sdev, plat_data->fw); + ret = load_modules(sdev, plat_data->fw, plat_data->fw_offset); if (ret < 0) { dev_err(sdev->dev, "error: invalid FW modules\n"); goto error; From e150ef4169a766aa20003506c0f25b5519981e80 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:56 -0500 Subject: [PATCH 043/428] ASoC: SOF: Introduce extended manifest Extended manifest is a place to store build time known firmware metadata, for example firmware version or used compiler description. Given information is read on host side before firmware startup. This part of output binary is located as a first structure in binary file. Extended manifest should be skipped in firmware loading routine. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 61 +++++++++++++ sound/soc/sof/loader.c | 122 ++++++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 include/uapi/sound/sof/ext_manifest.h diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h new file mode 100644 index 000000000000..fc4d1bec0cb3 --- /dev/null +++ b/include/uapi/sound/sof/ext_manifest.h @@ -0,0 +1,61 @@ +/* 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) 2020 Intel Corporation. All rights reserved. + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + */ + +#ifndef __SOF_FIRMWARE_EXT_MANIFEST_H__ +#define __SOF_FIRMWARE_EXT_MANIFEST_H__ + +#include + +/* In ASCII `XMan` */ +#define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 + +/* Build u32 number in format MMmmmppp */ +#define SOF_EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ((uint32_t)( \ + ((MAJOR) << 24) | \ + ((MINOR) << 12) | \ + (PATH))) + +/* check extended manifest version consistency */ +#define SOF_EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ + ((host_ver) & GENMASK(31, 24)) != \ + ((cli_ver) & GENMASK(31, 24))) + +/* used extended manifest header version */ +#define SOF_EXT_MAN_VERSION SOF_EXT_MAN_BUILD_VERSION(1, 0, 0) + +/* extended manifest header, deleting any field breaks backward compatibility */ +struct sof_ext_man_header { + uint32_t magic; /*< identification number, */ + /*< EXT_MAN_MAGIC_NUMBER */ + uint32_t full_size; /*< [bytes] full size of ext_man, */ + /*< (header + content + padding) */ + uint32_t header_size; /*< [bytes] makes header extensionable, */ + /*< after append new field to ext_man header */ + /*< then backward compatible won't be lost */ + uint32_t header_version; /*< value of EXT_MAN_VERSION */ + /*< not related with following content */ + uint8_t elements[]; /*< list of ext_man_elem_* elements */ +} __packed; + +/* Now define extended manifest elements */ + +/* extended manifest element header */ +struct sof_ext_man_elem_header { + uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ + uint32_t size; /*< in bytes, including header size */ + uint8_t blob[]; /*< type dependent content */ +} __packed; + +#endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 89f35db2577d..6b354b6fb83a 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -12,6 +12,7 @@ #include #include +#include #include "ops.h" static int get_ext_windows(struct snd_sof_dev *sdev, @@ -126,6 +127,104 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +static ssize_t snd_sof_ext_man_size(const struct firmware *fw) +{ + const struct sof_ext_man_header *head = (void *)fw->data; + + /* + * assert fw size is big enough to contain extended manifest header, + * it prevents from reading unallocated memory from `head` in following + * step. + */ + if (fw->size < sizeof(*head)) + return -EINVAL; + + /* + * When fw points to extended manifest, + * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER. + */ + if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER) + return head->full_size; + + /* otherwise given fw don't have an extended manifest */ + return 0; +} + +/* parse extended FW manifest data structures */ +static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, + const struct firmware *fw) +{ + const struct sof_ext_man_elem_header *elem_hdr; + const struct sof_ext_man_header *head; + ssize_t ext_man_size; + ssize_t remaining; + uintptr_t iptr; + int ret = 0; + + head = (struct sof_ext_man_header *)fw->data; + remaining = head->full_size - head->header_size; + ext_man_size = snd_sof_ext_man_size(fw); + + /* Assert firmware starts with extended manifest */ + if (ext_man_size < 0) { + dev_err(sdev->dev, "error: exception while reading firmware extended manifest, code %d\n", + (int)ext_man_size); + return ext_man_size; + } else if (!ext_man_size) { + dev_err(sdev->dev, "error: can't parse extended manifest when it's not present\n"); + return -EINVAL; + } + + /* incompatible version */ + if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION, + head->header_version)) { + dev_err(sdev->dev, "error: extended manifest version 0x%X differ from used 0x%X\n", + head->header_version, SOF_EXT_MAN_VERSION); + return -EINVAL; + } + + /* get first extended manifest element header */ + iptr = (uintptr_t)fw->data + head->header_size; + + while (remaining > sizeof(*elem_hdr)) { + elem_hdr = (struct sof_ext_man_elem_header *)iptr; + + dev_dbg(sdev->dev, "found sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + + if (elem_hdr->size < sizeof(*elem_hdr) || + elem_hdr->size > remaining) { + dev_err(sdev->dev, "error: invalid sof_ext_man header size, type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + break; + } + + /* process structure data */ + switch (elem_hdr->type) { + default: + dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + break; + } + + if (ret < 0) { + dev_err(sdev->dev, "error: failed to parse sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + break; + } + + remaining -= elem_hdr->size; + iptr += elem_hdr->size; + } + + if (remaining) { + dev_err(sdev->dev, "error: sof_ext_man header is inconsistent\n"); + ret = -EINVAL; + } + + return ret; +} + /* * IPC Firmware ready. */ @@ -473,6 +572,7 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; const char *fw_filename; + ssize_t ext_man_size; int ret; /* Don't request firmware again if firmware is already requested */ @@ -490,11 +590,33 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", fw_filename, ret); + goto err; } else { dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename); } + /* check for extended manifest */ + ext_man_size = snd_sof_ext_man_size(plat_data->fw); + if (ext_man_size > 0) { + ret = snd_sof_fw_ext_man_parse(sdev, plat_data->fw); + + /* when no error occurred, drop extended manifest */ + if (!ret) + plat_data->fw_offset = ext_man_size; + else + dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", + fw_filename, ret); + } else if (!ext_man_size) { + /* No extended manifest, so nothing to skip during FW load */ + dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n"); + } else { + ret = ext_man_size; + dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", + fw_filename, ret); + } + +err: kfree(fw_filename); return ret; From 371091417864b7be870eaad45e043059e6b6828a Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:57 -0500 Subject: [PATCH 044/428] ASoC: SOF: ext_manifest: parse firmware version The firmware version can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 13 +++++++++++++ sound/soc/sof/loader.c | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h index fc4d1bec0cb3..163d32210ad8 100644 --- a/include/uapi/sound/sof/ext_manifest.h +++ b/include/uapi/sound/sof/ext_manifest.h @@ -51,6 +51,11 @@ struct sof_ext_man_header { /* Now define extended manifest elements */ +/* Extended manifest elements types */ +enum sof_ext_man_elem_type { + SOF_EXT_MAN_ELEM_FW_VERSION = 0, +}; + /* extended manifest element header */ struct sof_ext_man_elem_header { uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ @@ -58,4 +63,12 @@ struct sof_ext_man_elem_header { uint8_t blob[]; /*< type dependent content */ } __packed; +/* FW version */ +struct sof_ext_man_fw_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_fw_version version; + uint32_t flags; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 6b354b6fb83a..01077c1ce235 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -127,6 +127,20 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +static int ext_man_get_fw_version(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_fw_version *v; + + v = container_of(hdr, struct sof_ext_man_fw_version, hdr); + + memcpy(&sdev->fw_ready.version, &v->version, sizeof(v->version)); + sdev->fw_ready.flags = v->flags; + + /* log ABI versions and check FW compatibility */ + return snd_sof_ipc_valid(sdev); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head = (void *)fw->data; @@ -201,6 +215,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, /* process structure data */ switch (elem_hdr->type) { + case SOF_EXT_MAN_ELEM_FW_VERSION: + ret = ext_man_get_fw_version(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); From 9e72f13ee541ccae34dd4a6735bcdf0c78090216 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:58 -0500 Subject: [PATCH 045/428] ASoC: SOF: ext_manifest: parse windows The window description can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 9 +++++++++ sound/soc/sof/loader.c | 27 +++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h index 163d32210ad8..203c203f6531 100644 --- a/include/uapi/sound/sof/ext_manifest.h +++ b/include/uapi/sound/sof/ext_manifest.h @@ -17,6 +17,7 @@ #define __SOF_FIRMWARE_EXT_MANIFEST_H__ #include +#include /* In ASCII `XMan` */ #define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 @@ -54,6 +55,7 @@ struct sof_ext_man_header { /* Extended manifest elements types */ enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, + SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, }; /* extended manifest element header */ @@ -71,4 +73,11 @@ struct sof_ext_man_fw_version { uint32_t flags; } __packed; +/* extended data memory windows for IPC, trace and debug */ +struct sof_ext_man_window { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_window ipc_window; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 01077c1ce235..bbfdf07fa6f5 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -20,13 +20,21 @@ static int get_ext_windows(struct snd_sof_dev *sdev, { const struct sof_ipc_window *w = container_of(ext_hdr, struct sof_ipc_window, ext_hdr); + size_t w_size = struct_size(w, window, w->num_windows); + + if (sdev->info_window) { + if (memcmp(sdev->info_window, w, w_size)) { + dev_err(sdev->dev, "error: mistmatch between window descriptor from extended manifest and mailbox"); + return -EINVAL; + } + return 0; + } if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) return -EINVAL; /* keep a local copy of the data */ - sdev->info_window = kmemdup(w, struct_size(w, window, w->num_windows), - GFP_KERNEL); + sdev->info_window = kmemdup(w, w_size, GFP_KERNEL); if (!sdev->info_window) return -ENOMEM; @@ -141,6 +149,18 @@ static int ext_man_get_fw_version(struct snd_sof_dev *sdev, return snd_sof_ipc_valid(sdev); } +static int ext_man_get_windows(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ipc_ext_data_hdr *w_ipc; + const struct sof_ext_man_window *w; + + w = container_of(hdr, struct sof_ext_man_window, hdr); + w_ipc = (const struct sof_ipc_ext_data_hdr *)&w->ipc_window; + + return get_ext_windows(sdev, w_ipc); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head = (void *)fw->data; @@ -218,6 +238,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_FW_VERSION: ret = ext_man_get_fw_version(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_WINDOW: + ret = ext_man_get_windows(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); From 7c024b948c206935e69aafa56187bff9dd36abed Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:59 -0500 Subject: [PATCH 046/428] ASoC: SOF: ext_manifest: parse compiler version The compiler version and description can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 8 ++++++++ sound/soc/sof/loader.c | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h index 203c203f6531..d49c47d08c7f 100644 --- a/include/uapi/sound/sof/ext_manifest.h +++ b/include/uapi/sound/sof/ext_manifest.h @@ -56,6 +56,7 @@ struct sof_ext_man_header { enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, + SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, }; /* extended manifest element header */ @@ -80,4 +81,11 @@ struct sof_ext_man_window { struct sof_ipc_window ipc_window; } __packed; +/* Used C compiler description */ +struct sof_ext_man_cc_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_cc_version cc_version; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index bbfdf07fa6f5..8be30cd5e038 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -49,6 +49,14 @@ static int get_cc_info(struct snd_sof_dev *sdev, const struct sof_ipc_cc_version *cc = container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); + if (sdev->cc_version) { + if (memcmp(sdev->cc_version, cc, cc->ext_hdr.hdr.size)) { + dev_err(sdev->dev, "error: receive diverged cc_version descriptions"); + return -EINVAL; + } + return 0; + } + dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", cc->name, cc->major, cc->minor, cc->micro, cc->desc, cc->optim); @@ -161,6 +169,18 @@ static int ext_man_get_windows(struct snd_sof_dev *sdev, return get_ext_windows(sdev, w_ipc); } +static int ext_man_get_cc_info(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_cc_version *cc; + const struct sof_ipc_ext_data_hdr *cc_version; + + cc = container_of(hdr, struct sof_ext_man_cc_version, hdr); + cc_version = (const struct sof_ipc_ext_data_hdr *)&cc->cc_version; + + return get_cc_info(sdev, cc_version); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head = (void *)fw->data; @@ -241,6 +261,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_WINDOW: ret = ext_man_get_windows(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_CC_VERSION: + ret = ext_man_get_cc_info(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); From 542adb2a461fb63711b96b1179f070b4fa79cc37 Mon Sep 17 00:00:00 2001 From: Sebastiano Carlucci Date: Wed, 15 Apr 2020 15:28:00 -0500 Subject: [PATCH 047/428] ASoC: SOF: topology: Add support for DC Blocker This commit adds the enumerations to support the dc blocker component from SOF. Signed-off-by: Sebastiano Carlucci Signed-off-by: Pierre-Louis Bossart Reviewed-by: Curtis Malainey Reviewed-by: Seppo Ingalsuo Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 2 ++ sound/soc/sof/topology.c | 1 + 2 files changed, 3 insertions(+) diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 402e0250c508..8f8d1cf649f2 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -37,6 +37,7 @@ enum sof_comp_type { SOF_COMP_SELECTOR, /**< channel selector component */ SOF_COMP_DEMUX, SOF_COMP_ASRC, /**< Asynchronous sample rate converter */ + SOF_COMP_DCBLOCK, /* 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 */ @@ -206,6 +207,7 @@ enum sof_ipc_process_type { SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */ SOF_PROCESS_MUX, SOF_PROCESS_DEMUX, + SOF_PROCESS_DCBLOCK, }; /* generic "effect", "codec" or proprietary processing component */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3386886fd743..e988e6b1a594 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -430,6 +430,7 @@ static const struct sof_process_types sof_process[] = { {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR}, {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, + {"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK}, }; static enum sof_ipc_process_type find_process(const char *name) From 786d6516877dc852392117d44a77bf3093c39dbd Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:01 -0500 Subject: [PATCH 048/428] ASoC: SOF: add probe support extend data Share how many injection probe DMAs and how many probe points driver can request from FW. injection_dmas_max 0 means injection is not supported probe_points_max 0 means whole probes subsystem in FW is not enabled and not compiled in. ABI version change to 3.14.0 Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/info.h | 12 ++++++++++++ include/uapi/sound/sof/abi.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 438a11fcf272..68e92b550439 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -31,6 +31,7 @@ enum sof_ipc_ext_data { SOF_IPC_EXT_UNUSED = 0, SOF_IPC_EXT_WINDOW = 1, SOF_IPC_EXT_CC_INFO = 2, + SOF_IPC_EXT_PROBE_INFO = 3, }; /* FW version - SOF_IPC_GLB_VERSION */ @@ -114,4 +115,15 @@ struct sof_ipc_cc_version { char desc[]; /* null terminated compiler description */ } __packed; +/* extended data: Probe setup */ +struct sof_ipc_probe_support { + struct sof_ipc_ext_data_hdr ext_hdr; + + uint32_t probe_points_max; + uint32_t injection_dmas_max; + + /* reserved for future use */ + uint32_t reserved[2]; +} __packed; + #endif diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 5995b79d6df1..e0fa2939d49c 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 13 +#define SOF_ABI_MINOR 14 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ From 2014185eba4e061db038a59a6e1d85e88291edc6 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:02 -0500 Subject: [PATCH 049/428] ASoC: SOF: add debug ABI version Add new debug ABI version to be increased when changing user space debug interfaces while the the main FW ABI is not affected. The abi_dbg_version share same definition with SOF_ABI_VER This change main ABI to 3.14.0 Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/info.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 68e92b550439..162f38430958 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -32,6 +32,7 @@ enum sof_ipc_ext_data { SOF_IPC_EXT_WINDOW = 1, SOF_IPC_EXT_CC_INFO = 2, SOF_IPC_EXT_PROBE_INFO = 3, + SOF_IPC_EXT_USER_ABI_INFO = 4, }; /* FW version - SOF_IPC_GLB_VERSION */ @@ -126,4 +127,11 @@ struct sof_ipc_probe_support { uint32_t reserved[2]; } __packed; +/* extended data: user abi version(s) */ +struct sof_ipc_user_abi_version { + struct sof_ipc_ext_data_hdr ext_hdr; + + uint32_t abi_dbg_version; +} __packed; + #endif From e6224484454da920874db9ad30ea9b493f5600bd Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:03 -0500 Subject: [PATCH 050/428] ASoC: SOF: change type char to uint8_t in info.h Use uint8_t to replace char in packed ABI structs to have fixed length for struct. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/info.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 162f38430958..2ef98b2fee1f 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -111,9 +111,9 @@ struct sof_ipc_cc_version { /* reserved for future use */ uint32_t reserved[4]; - char name[16]; /* null terminated compiler name */ - char optim[4]; /* null terminated compiler -O flag value */ - char desc[]; /* null terminated compiler description */ + uint8_t name[16]; /* null terminated compiler name */ + uint8_t optim[4]; /* null terminated compiler -O flag value */ + uint8_t desc[]; /* null terminated compiler description */ } __packed; /* extended data: Probe setup */ From f480f804f27a3decd03682b707453963bb8b4162 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:04 -0500 Subject: [PATCH 051/428] ASoC: SOF: change type char to uint8_t in trace.h Use uint8_t to replace char in packed ABI structs to have fixed length for struct. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h index fda6e8f6ead4..8056f214946d 100644 --- a/include/sound/sof/trace.h +++ b/include/sound/sof/trace.h @@ -72,7 +72,7 @@ struct sof_ipc_dma_trace_posn { struct sof_ipc_panic_info { struct sof_ipc_hdr hdr; uint32_t code; /* SOF_IPC_PANIC_ */ - char filename[SOF_TRACE_FILENAME_SIZE]; + uint8_t filename[SOF_TRACE_FILENAME_SIZE]; uint32_t linenum; } __packed; From 60829341aa602b74f5f5b9d903e0b809557a54a4 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:05 -0500 Subject: [PATCH 052/428] ASoC: SOF: change type char to uint8_t in topology.h Use uint8_t to replace char in packed ABI structs to have fixed length for struct. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 8f8d1cf649f2..6a6b4791eaf6 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -220,7 +220,7 @@ struct sof_ipc_comp_process { /* reserved for future use */ uint32_t reserved[7]; - unsigned char data[0]; + uint8_t data[0]; } __packed; /* frees components, buffers and pipelines From a9a9cbf081414de0261279e3b11ada2f0a7f7e83 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:06 -0500 Subject: [PATCH 053/428] ASoC: SOF: make sof_ipc_cc_version to fixed length Align struct sof_ipc_cc_version to firmware definition in SOF ABI 3.15.0. The struct definition was changed due to errors in FW build. The Cadence XCC compiler produces incorrect linkage section sizes, when a variable length array is used in the compiler version struct. The firmware definition was changed to a fixed 32 byte compiler description string. This length covers all released firmware binaries and thus only a minor ABI change is needed. As the same structure is used in IPC messages between driver and firmware, the kernel needs to be aligned to firmware change. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/info.h | 2 +- include/uapi/sound/sof/abi.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 2ef98b2fee1f..d5eff3179a39 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -113,7 +113,7 @@ struct sof_ipc_cc_version { uint8_t name[16]; /* null terminated compiler name */ uint8_t optim[4]; /* null terminated compiler -O flag value */ - uint8_t desc[]; /* null terminated compiler description */ + uint8_t desc[32]; /* null terminated compiler description */ } __packed; /* extended data: Probe setup */ diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index e0fa2939d49c..6c802a2386ef 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 14 +#define SOF_ABI_MINOR 15 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ From 7893df67e9bde8e4f0ede579ff874d438af620d8 Mon Sep 17 00:00:00 2001 From: Artur Kloniecki Date: Wed, 15 Apr 2020 15:28:07 -0500 Subject: [PATCH 054/428] ASoC: SOF: Add XRUN flags field to struct sof_ipc_buffer. Currently if a component source buffer underruns or a component sink buffer overruns the pipeline will enter an XRUN status and attempt recovery. This is desired in most pipelines but some topologies need to support use cases where we expect buffers to underrun or overrun. Host ---> Proc----> Selector0 --> Buf0 ---- > DAI Playback | v Buf1 | v Host <---------------Selector1 <----- Buf2 <----- Echo Ref DAI In the example above we two host PCMs that can be independently started/stopped thereby causing buf1 to either underrun or overrun (and stop the pipelines). Buf1 should be permitted to underrun or overrun without invoking pipeline XRUN logic and should over write oldest data (for overrun) and readback 0s (for underrun). 2 flags have been added for use during buffer instantiation: SOF_BUF_OVERRUN_PERMITTED and SOF_BUF_UNDERRUN_PERMITTED, along with struct sof_ipc_buffer member fields: flags and reserved. Flags field is supposed to hold the above-mentioned flags to allow some control over XRUN behaviour. Also added reserved field to the structure in case it comes in handy some time in the future. This is an incremental ABI change as the new fields are ignored by older versions of the firmware. Signed-off-by: Artur Kloniecki Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 6a6b4791eaf6..08267d284edc 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -76,11 +76,23 @@ struct sof_ipc_comp { #define SOF_MEM_CAPS_CACHE (1 << 6) /**< cacheable */ #define SOF_MEM_CAPS_EXEC (1 << 7) /**< executable */ +/* + * overrun will cause ring buffer overwrite, instead of XRUN. + */ +#define SOF_BUF_OVERRUN_PERMITTED BIT(0) + +/* + * underrun will cause readback of 0s, instead of XRUN. + */ +#define SOF_BUF_UNDERRUN_PERMITTED BIT(1) + /* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */ struct sof_ipc_buffer { struct sof_ipc_comp comp; uint32_t size; /**< buffer size in bytes */ uint32_t caps; /**< SOF_MEM_CAPS_ */ + uint32_t flags; /**< SOF_BUF_ flags defined above */ + uint32_t reserved; /**< reserved for future use */ } __packed; /* generic component config data - must always be after struct sof_ipc_comp */ From 79a4ff94a3fcb76d9650341336f4779f6d48d325 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Wed, 15 Apr 2020 15:28:08 -0500 Subject: [PATCH 055/428] ASoC: SOF: Intel: Fix typo in header file comment text This patch fixes the typo in word "microphone". Signed-off-by: Seppo Ingalsuo Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 04e48227f542..988cddb8b04b 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -135,7 +135,7 @@ struct sof_ipc_dai_dmic_pdm_ctrl { * version number used in configuration data is checked vs. version used by * device driver src/drivers/dmic.c need to match. It is incremented from * initial value 1 if updates done for the to driver would alter the operation - * of the microhone. + * of the microphone. * * Note: The microphone clock (pdmclk_min, pdmclk_max, duty_min, duty_max) * parameters need to be set as defined in microphone data sheet. E.g. clock From 31be5337ace110b6c9a567c05b661fd8168ef8cc Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Wed, 15 Apr 2020 15:28:09 -0500 Subject: [PATCH 056/428] ASoC: SOF: Intel: Change DMIC load IPC to fixed length This patch changes the flexible array member pdm[] into a fixed array of four that is the max. number of stereo PDM controllers in the current Intel platforms. The change simplifies DMIC DAI load code and aligns the IPC with other DAI types. The change is compatible with old and new firmware with similar change. The ABI minor version is increased due to change in IPC headers. Signed-off-by: Seppo Ingalsuo Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 10 +++-- sound/soc/sof/topology.c | 75 ++++++++++++----------------------- 2 files changed, 32 insertions(+), 53 deletions(-) diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 988cddb8b04b..59fa73f3e34d 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -49,6 +49,9 @@ /* bclk idle */ #define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5) +/* DMIC max. four controllers for eight microphone channels */ +#define SOF_DAI_INTEL_DMIC_NUM_CTRL 4 + /* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */ struct sof_ipc_dai_ssp_params { struct sof_ipc_hdr hdr; @@ -175,7 +178,8 @@ struct sof_ipc_dai_dmic_params { uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */ uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */ - uint32_t num_pdm_active; /**< Number of active pdm controllers */ + uint32_t num_pdm_active; /**< Number of active pdm controllers. */ + /**< Range is 1..SOF_DAI_INTEL_DMIC_NUM_CTRL */ 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) */ @@ -184,8 +188,8 @@ struct sof_ipc_dai_dmic_params { /* reserved for future use */ uint32_t reserved[5]; - /**< variable number of pdm controller config */ - struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; + /**< PDM controllers configuration */ + struct sof_ipc_dai_dmic_pdm_ctrl pdm[SOF_DAI_INTEL_DMIC_NUM_CTRL]; } __packed; #endif diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index e988e6b1a594..602406ff8e4c 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2891,18 +2891,13 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; - struct sof_ipc_dai_config *ipc_config; struct sof_ipc_reply reply; struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; - u32 size; + size_t size = sizeof(*config); int ret, j; - /* - * config is only used for the common params in dmic_params structure - * that does not include the PDM controller config array - * Set the common params to 0. - */ + /* Ensure the entire DMIC config struct is zeros */ memset(&config->dmic, 0, sizeof(struct sof_ipc_dai_dmic_params)); /* get DMIC tokens */ @@ -2915,33 +2910,16 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, return ret; } - /* - * allocate memory for dmic dai config accounting for the - * variable number of active pdm controllers - * This will be the ipc payload for setting dai config - */ - size = sizeof(*config) + sizeof(struct sof_ipc_dai_dmic_pdm_ctrl) * - config->dmic.num_pdm_active; - - ipc_config = kzalloc(size, GFP_KERNEL); - if (!ipc_config) - return -ENOMEM; - - /* copy the common dai config and dmic params */ - memcpy(ipc_config, config, sizeof(*config)); - /* * alloc memory for private member * Used to track the pdm config array index currently being parsed */ sdev->private = kzalloc(sizeof(u32), GFP_KERNEL); - if (!sdev->private) { - kfree(ipc_config); + if (!sdev->private) return -ENOMEM; - } /* get DMIC PDM tokens */ - ret = sof_parse_tokens(scomp, &ipc_config->dmic.pdm[0], dmic_pdm_tokens, + ret = sof_parse_tokens(scomp, &config->dmic.pdm[0], dmic_pdm_tokens, ARRAY_SIZE(dmic_pdm_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { @@ -2951,44 +2929,42 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, } /* set IPC header size */ - ipc_config->hdr.size = size; + config->hdr.size = size; /* debug messages */ dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n", - ipc_config->dai_index, ipc_config->dmic.driver_ipc_version); + config->dai_index, config->dmic.driver_ipc_version); dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n", - ipc_config->dmic.pdmclk_min, ipc_config->dmic.pdmclk_max, - ipc_config->dmic.duty_min); + config->dmic.pdmclk_min, config->dmic.pdmclk_max, + config->dmic.duty_min); dev_dbg(scomp->dev, "duty_max %hd fifo_fs %d num_pdms active %d\n", - ipc_config->dmic.duty_max, ipc_config->dmic.fifo_fs, - ipc_config->dmic.num_pdm_active); - dev_dbg(scomp->dev, "fifo word length %hd\n", - ipc_config->dmic.fifo_bits); + config->dmic.duty_max, config->dmic.fifo_fs, + config->dmic.num_pdm_active); + dev_dbg(scomp->dev, "fifo word length %hd\n", config->dmic.fifo_bits); - for (j = 0; j < ipc_config->dmic.num_pdm_active; j++) { + for (j = 0; j < config->dmic.num_pdm_active; j++) { dev_dbg(scomp->dev, "pdm %hd mic a %hd mic b %hd\n", - ipc_config->dmic.pdm[j].id, - ipc_config->dmic.pdm[j].enable_mic_a, - ipc_config->dmic.pdm[j].enable_mic_b); + config->dmic.pdm[j].id, + config->dmic.pdm[j].enable_mic_a, + config->dmic.pdm[j].enable_mic_b); dev_dbg(scomp->dev, "pdm %hd polarity a %hd polarity b %hd\n", - ipc_config->dmic.pdm[j].id, - ipc_config->dmic.pdm[j].polarity_mic_a, - ipc_config->dmic.pdm[j].polarity_mic_b); + config->dmic.pdm[j].id, + config->dmic.pdm[j].polarity_mic_a, + config->dmic.pdm[j].polarity_mic_b); dev_dbg(scomp->dev, "pdm %hd clk_edge %hd skew %hd\n", - ipc_config->dmic.pdm[j].id, - ipc_config->dmic.pdm[j].clk_edge, - ipc_config->dmic.pdm[j].skew); + config->dmic.pdm[j].id, + config->dmic.pdm[j].clk_edge, + config->dmic.pdm[j].skew); } if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) { /* this takes care of backwards compatible handling of fifo_bits_b */ - ipc_config->dmic.reserved_2 = ipc_config->dmic.fifo_bits; + config->dmic.reserved_2 = config->dmic.fifo_bits; } /* send message to DSP */ - ret = sof_ipc_tx_message(sdev->ipc, - ipc_config->hdr.cmd, ipc_config, size, &reply, - sizeof(reply)); + ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, + &reply, sizeof(reply)); if (ret < 0) { dev_err(scomp->dev, @@ -2998,14 +2974,13 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, } /* set config for all DAI's with name matching the link name */ - ret = sof_set_dai_config(sdev, size, link, ipc_config); + ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) dev_err(scomp->dev, "error: failed to save DAI config for DMIC%d\n", config->dai_index); err: kfree(sdev->private); - kfree(ipc_config); return ret; } From 1993ba26cc53a98aa67c451d735249e221ddd39d Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Wed, 15 Apr 2020 15:28:10 -0500 Subject: [PATCH 057/428] ASoC: SOF: Intel: Rename deprecated DMIC IPC struct field This patch restores the field name to fifo_bits_b since the legacy firmware compatibility code (for firmware ABI 3.0.0 or earlier) sets it in sof_link_dmic_load() function in topology.c. Setting of reserved_2 didn't look appropriate. Signed-off-by: Seppo Ingalsuo Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 2 +- sound/soc/sof/topology.c | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 59fa73f3e34d..4dcea5aed878 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -173,7 +173,7 @@ struct sof_ipc_dai_dmic_params { uint32_t fifo_fs; /**< FIFO sample rate in Hz (8000..96000) */ uint32_t reserved_1; /**< Reserved */ uint16_t fifo_bits; /**< FIFO word length (16 or 32) */ - uint16_t reserved_2; /**< Reserved */ + uint16_t fifo_bits_b; /**< Deprecated since firmware ABI 3.0.1 */ uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */ uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 602406ff8e4c..3670b4221ba6 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2957,10 +2957,12 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, config->dmic.pdm[j].skew); } - if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) { - /* this takes care of backwards compatible handling of fifo_bits_b */ - config->dmic.reserved_2 = config->dmic.fifo_bits; - } + /* + * this takes care of backwards compatible handling of fifo_bits_b. + * It is deprecated since firmware ABI version 3.0.1. + */ + if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) + config->dmic.fifo_bits_b = config->dmic.fifo_bits; /* send message to DSP */ ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, From 1f846505b3651ac385762b794868922e2be83d42 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 15 Apr 2020 15:28:11 -0500 Subject: [PATCH 058/428] ASoC: SOF: align sof_ipc_dai_alh_params with FW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aligned with FW change. The rate and channel values are needed in case of a connection with a demux for synchronize playback over multiple ALH DAIs. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: SÅ‚awomir BÅ‚auciak Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 4dcea5aed878..4db906c4a534 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -94,9 +94,11 @@ struct sof_ipc_dai_hda_params { struct sof_ipc_dai_alh_params { struct sof_ipc_hdr hdr; uint32_t stream_id; + uint32_t rate; + uint32_t channels; /* reserved for future use */ - uint32_t reserved[15]; + uint32_t reserved[13]; } __packed; /* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */ From c7fc96dfc41d168e94d26c455123193e6e59bf24 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 15 Apr 2020 15:28:12 -0500 Subject: [PATCH 059/428] ASoC: SOF: topology: Get ALH rate amd channels from topology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FW will need these params for synchronized playback over multiple DAIs. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: SÅ‚awomir BÅ‚auciak Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 4 ++++ sound/soc/sof/topology.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 2a25cd8da503..b7ad1cd4526a 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -126,4 +126,8 @@ #define SOF_TKN_MUTE_LED_USE 1300 #define SOF_TKN_MUTE_LED_DIRECTION 1301 +/* ALH */ +#define SOF_TKN_INTEL_ALH_RATE 1400 +#define SOF_TKN_INTEL_ALH_CH 1401 + #endif diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3670b4221ba6..f59c34bb085b 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -656,6 +656,16 @@ static const struct sof_topology_token ssp_tokens[] = { }; +/* ALH */ +static const struct sof_topology_token alh_tokens[] = { + {SOF_TKN_INTEL_ALH_RATE, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_alh_params, rate), 0}, + {SOF_TKN_INTEL_ALH_CH, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_alh_params, channels), 0}, +}; + /* DMIC */ static const struct sof_topology_token dmic_tokens[] = { {SOF_TKN_INTEL_DMIC_DRIVER_VERSION, @@ -3095,13 +3105,26 @@ static int sof_link_alh_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_tplg_private *private = &cfg->priv; struct sof_ipc_reply reply; u32 size = sizeof(*config); int ret; + ret = sof_parse_tokens(scomp, &config->alh, alh_tokens, + ARRAY_SIZE(alh_tokens), private->array, + le32_to_cpu(private->size)); + if (ret != 0) { + dev_err(scomp->dev, "error: parse alh tokens failed %d\n", + le32_to_cpu(private->size)); + return ret; + } + /* init IPC */ config->hdr.size = size; + dev_dbg(scomp->dev, "ALH config rate %d channels %d\n", + config->alh.rate, config->alh.channels); + /* send message to DSP */ ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, &reply, From 15bf1831fc91a447e336ef252b48d5f9cad8a3f2 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 15 Apr 2020 15:28:13 -0500 Subject: [PATCH 060/428] ASoC: SOF: topology: fix: parse hda_tokens to &config->hda Items in hda_tokens are for &config->hda. So fix it to the right object. This error has been harmless as hda_tokens array was empty. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index f59c34bb085b..51d19ffe35b3 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3074,7 +3074,7 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, config->hdr.size = size; /* get any bespoke DAI tokens */ - ret = sof_parse_tokens(scomp, config, hda_tokens, + ret = sof_parse_tokens(scomp, &config->hda, hda_tokens, ARRAY_SIZE(hda_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { From 18aaab64fbb121e5879f74a46903bcfd30bf660b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 15 Apr 2020 15:28:14 -0500 Subject: [PATCH 061/428] ASoC: SOF: topology: Get HDA rate and channels from topology FW interface for HDA DAI parameters was extended with information on sampling rate and channel count in version 3.16. Align kernel header with the FW change. This change is backwards compatible. Old firmware will ignore the values. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 2 ++ include/uapi/sound/sof/abi.h | 2 +- include/uapi/sound/sof/tokens.h | 4 ++++ sound/soc/sof/topology.c | 9 +++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 4db906c4a534..896db2243d87 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -88,6 +88,8 @@ struct sof_ipc_dai_ssp_params { struct sof_ipc_dai_hda_params { struct sof_ipc_hdr hdr; uint32_t link_dma_ch; + uint32_t rate; + uint32_t channels; } __packed; /* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */ diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 6c802a2386ef..d54be303090f 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 15 +#define SOF_ABI_MINOR 16 #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 b7ad1cd4526a..5941e2eb1588 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -130,4 +130,8 @@ #define SOF_TKN_INTEL_ALH_RATE 1400 #define SOF_TKN_INTEL_ALH_CH 1401 +/* HDA */ +#define SOF_TKN_INTEL_HDA_RATE 1500 +#define SOF_TKN_INTEL_HDA_CH 1501 + #endif diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 51d19ffe35b3..a1287924a12d 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -753,6 +753,12 @@ static const struct sof_topology_token dmic_pdm_tokens[] = { /* HDA */ static const struct sof_topology_token hda_tokens[] = { + {SOF_TKN_INTEL_HDA_RATE, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_hda_params, rate), 0}, + {SOF_TKN_INTEL_HDA_CH, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_hda_params, channels), 0}, }; /* Leds */ @@ -3083,6 +3089,9 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, return ret; } + dev_dbg(scomp->dev, "HDA config rate %d channels %d\n", + config->hda.rate, config->hda.channels); + dai = snd_soc_find_dai(link->cpus); if (!dai) { dev_err(scomp->dev, "error: failed to find dai %s in %s", From f228a5b1703871632adb0918774386409cef05c5 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Wed, 15 Apr 2020 15:28:15 -0500 Subject: [PATCH 062/428] ASoC: SOF: topology: stop parsing when all tokens have been found Optimize the parsing so that it will stop after all required tokens have been found as there is no reason to continue after that. Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-24-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 60 +++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index a1287924a12d..d4d0c39d6e6e 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -769,13 +769,14 @@ static const struct sof_topology_token led_tokens[] = { get_token_u32, offsetof(struct snd_sof_led_control, direction), 0}, }; -static void sof_parse_uuid_tokens(struct snd_soc_component *scomp, - void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array) +static int sof_parse_uuid_tokens(struct snd_soc_component *scomp, + void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array) { struct snd_soc_tplg_vendor_uuid_elem *elem; + int found = 0; int i, j; /* parse element by element */ @@ -795,17 +796,22 @@ static void sof_parse_uuid_tokens(struct snd_soc_component *scomp, /* matched - now load token */ tokens[j].get_token(elem, object, tokens[j].offset, tokens[j].size); + + found++; } } + + return found; } -static void sof_parse_string_tokens(struct snd_soc_component *scomp, - void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array) +static int sof_parse_string_tokens(struct snd_soc_component *scomp, + void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array) { struct snd_soc_tplg_vendor_string_elem *elem; + int found = 0; int i, j; /* parse element by element */ @@ -825,19 +831,24 @@ static void sof_parse_string_tokens(struct snd_soc_component *scomp, /* matched - now load token */ tokens[j].get_token(elem, object, tokens[j].offset, tokens[j].size); + + found++; } } + + return found; } -static void sof_parse_word_tokens(struct snd_soc_component *scomp, - void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array) +static int sof_parse_word_tokens(struct snd_soc_component *scomp, + void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_vendor_value_elem *elem; size_t size = sizeof(struct sof_ipc_dai_dmic_pdm_ctrl); + int found = 0; int i, j; u32 offset; u32 *index = NULL; @@ -897,8 +908,12 @@ static void sof_parse_word_tokens(struct snd_soc_component *scomp, tokens[j].get_token(elem, object, offset + tokens[j].offset, tokens[j].size); + + found++; } } + + return found; } static int sof_parse_tokens(struct snd_soc_component *scomp, @@ -908,9 +923,10 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, struct snd_soc_tplg_vendor_array *array, int priv_size) { + int found = 0; int asize; - while (priv_size > 0) { + while (priv_size > 0 && found < count) { asize = le32_to_cpu(array->size); /* validate asize */ @@ -931,19 +947,19 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, /* call correct parser depending on type */ switch (le32_to_cpu(array->type)) { case SND_SOC_TPLG_TUPLE_TYPE_UUID: - sof_parse_uuid_tokens(scomp, object, tokens, count, - array); + found += sof_parse_uuid_tokens(scomp, object, tokens, + count, array); break; case SND_SOC_TPLG_TUPLE_TYPE_STRING: - sof_parse_string_tokens(scomp, object, tokens, count, - array); + found += sof_parse_string_tokens(scomp, object, tokens, + count, array); break; case SND_SOC_TPLG_TUPLE_TYPE_BOOL: case SND_SOC_TPLG_TUPLE_TYPE_BYTE: case SND_SOC_TPLG_TUPLE_TYPE_WORD: case SND_SOC_TPLG_TUPLE_TYPE_SHORT: - sof_parse_word_tokens(scomp, object, tokens, count, - array); + found += sof_parse_word_tokens(scomp, object, tokens, + count, array); break; default: dev_err(scomp->dev, "error: unknown token type %d\n", From a1687c68c3089ed746c18f2121c8e63e2cf22c00 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Wed, 15 Apr 2020 15:28:16 -0500 Subject: [PATCH 063/428] ASoC: SOF: topology: handle multiple sets of tuple arrays Widget's parameters are set in topology and they usually consist of several different types of tuple arrays like strings, words and bytes. Here this kind of combination is called a "set". Lately we've seen more complex widget definitions with multiple identical sets of tuple arrays. One example is the dmic pdm configuration, which is currently handled as a special case in token parsing. This is not scalable for other components with multiple sets. So add a new function sof_parse_token_sets, which can be used to parse multiple sets. This function defines the number of sets and an offset to copy the tokens to correct positions in the destination ipc struct. Old sof_parse_token function will be a special case of calling sof_parse_token_sets to parse 1 set with offset 0. Finally modify the dmic dai link loading to use the new sof_parse_array_sets to load multiple pdm configs. Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-25-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 121 +++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 55 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index d4d0c39d6e6e..e88ffc25025f 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -773,7 +773,8 @@ static int sof_parse_uuid_tokens(struct snd_soc_component *scomp, void *object, const struct sof_topology_token *tokens, int count, - struct snd_soc_tplg_vendor_array *array) + struct snd_soc_tplg_vendor_array *array, + size_t offset) { struct snd_soc_tplg_vendor_uuid_elem *elem; int found = 0; @@ -794,7 +795,8 @@ static int sof_parse_uuid_tokens(struct snd_soc_component *scomp, continue; /* matched - now load token */ - tokens[j].get_token(elem, object, tokens[j].offset, + tokens[j].get_token(elem, object, + offset + tokens[j].offset, tokens[j].size); found++; @@ -808,7 +810,8 @@ static int sof_parse_string_tokens(struct snd_soc_component *scomp, void *object, const struct sof_topology_token *tokens, int count, - struct snd_soc_tplg_vendor_array *array) + struct snd_soc_tplg_vendor_array *array, + size_t offset) { struct snd_soc_tplg_vendor_string_elem *elem; int found = 0; @@ -829,7 +832,8 @@ static int sof_parse_string_tokens(struct snd_soc_component *scomp, continue; /* matched - now load token */ - tokens[j].get_token(elem, object, tokens[j].offset, + tokens[j].get_token(elem, object, + offset + tokens[j].offset, tokens[j].size); found++; @@ -843,15 +847,12 @@ static int sof_parse_word_tokens(struct snd_soc_component *scomp, void *object, const struct sof_topology_token *tokens, int count, - struct snd_soc_tplg_vendor_array *array) + struct snd_soc_tplg_vendor_array *array, + size_t offset) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_vendor_value_elem *elem; - size_t size = sizeof(struct sof_ipc_dai_dmic_pdm_ctrl); int found = 0; int i, j; - u32 offset; - u32 *index = NULL; /* parse element by element */ for (i = 0; i < le32_to_cpu(array->num_elems); i++) { @@ -870,40 +871,6 @@ static int sof_parse_word_tokens(struct snd_soc_component *scomp, if (tokens[j].token != le32_to_cpu(elem->token)) continue; - /* pdm config array index */ - if (sdev->private) - index = sdev->private; - - /* matched - determine offset */ - switch (tokens[j].token) { - case SOF_TKN_INTEL_DMIC_PDM_CTRL_ID: - - /* inc number of pdm array index */ - if (index) - (*index)++; - /* fallthrough */ - case SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable: - case SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable: - case SOF_TKN_INTEL_DMIC_PDM_POLARITY_A: - case SOF_TKN_INTEL_DMIC_PDM_POLARITY_B: - case SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE: - case SOF_TKN_INTEL_DMIC_PDM_SKEW: - - /* check if array index is valid */ - if (!index || *index == 0) { - dev_err(scomp->dev, - "error: invalid array offset\n"); - continue; - } else { - /* offset within the pdm config array */ - offset = size * (*index - 1); - } - break; - default: - offset = 0; - break; - } - /* load token */ tokens[j].get_token(elem, object, offset + tokens[j].offset, @@ -916,17 +883,33 @@ static int sof_parse_word_tokens(struct snd_soc_component *scomp, return found; } -static int sof_parse_tokens(struct snd_soc_component *scomp, - void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array, - int priv_size) +/** + * sof_parse_token_sets - Parse multiple sets of tokens + * @scomp: pointer to soc component + * @object: target ipc struct for parsed values + * @tokens: token definition array describing what tokens to parse + * @count: number of tokens in definition array + * @array: source pointer to consecutive vendor arrays to be parsed + * @priv_size: total size of the consecutive source arrays + * @sets: number of similar token sets to be parsed, 1 set has count elements + * @object_size: offset to next target ipc struct with multiple sets + * + * This function parses multiple sets of tokens in vendor arrays into + * consecutive ipc structs. + */ +static int sof_parse_token_sets(struct snd_soc_component *scomp, + void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array, + int priv_size, int sets, size_t object_size) { + size_t offset = 0; int found = 0; + int total = 0; int asize; - while (priv_size > 0 && found < count) { + while (priv_size > 0 && total < count * sets) { asize = le32_to_cpu(array->size); /* validate asize */ @@ -948,18 +931,18 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, switch (le32_to_cpu(array->type)) { case SND_SOC_TPLG_TUPLE_TYPE_UUID: found += sof_parse_uuid_tokens(scomp, object, tokens, - count, array); + count, array, offset); break; case SND_SOC_TPLG_TUPLE_TYPE_STRING: found += sof_parse_string_tokens(scomp, object, tokens, - count, array); + count, array, offset); break; case SND_SOC_TPLG_TUPLE_TYPE_BOOL: case SND_SOC_TPLG_TUPLE_TYPE_BYTE: case SND_SOC_TPLG_TUPLE_TYPE_WORD: case SND_SOC_TPLG_TUPLE_TYPE_SHORT: found += sof_parse_word_tokens(scomp, object, tokens, - count, array); + count, array, offset); break; default: dev_err(scomp->dev, "error: unknown token type %d\n", @@ -970,10 +953,35 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, /* next array */ array = (struct snd_soc_tplg_vendor_array *)((u8 *)array + asize); + + /* move to next target struct */ + if (found >= count) { + offset += object_size; + total += found; + found = 0; + } } + return 0; } +static int sof_parse_tokens(struct snd_soc_component *scomp, + void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array, + int priv_size) +{ + /* + * sof_parse_tokens is used when topology contains only a single set of + * identical tuples arrays. So additional parameters to + * sof_parse_token_sets are sets = 1 (only 1 set) and + * object_size = 0 (irrelevant). + */ + return sof_parse_token_sets(scomp, object, tokens, count, array, + priv_size, 1, 0); +} + static void sof_dbg_comp_config(struct snd_soc_component *scomp, struct sof_ipc_comp_config *config) { @@ -2951,9 +2959,12 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, return -ENOMEM; /* get DMIC PDM tokens */ - ret = sof_parse_tokens(scomp, &config->dmic.pdm[0], dmic_pdm_tokens, + ret = sof_parse_token_sets(scomp, &config->dmic.pdm[0], dmic_pdm_tokens, ARRAY_SIZE(dmic_pdm_tokens), private->array, - le32_to_cpu(private->size)); + le32_to_cpu(private->size), + config->dmic.num_pdm_active, + sizeof(struct sof_ipc_dai_dmic_pdm_ctrl)); + if (ret != 0) { dev_err(scomp->dev, "error: parse dmic pdm tokens failed %d\n", le32_to_cpu(private->size)); From 35c638d039bbabbca7affb52960d468951d811c1 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Wed, 15 Apr 2020 10:11:58 +0200 Subject: [PATCH 064/428] ASoC: qdsp6: Suggest more generic node names Change the listed examples to use more generic node names, representing the class of the device nodes: - apr-service@ - dai@ Both names are already in use in arch/arm64/boot/dts/qcom/sdm845.dtsi. Also add #address-cells + #size-cells to the q6asm example, without them the example produces dtc warnings. Signed-off-by: Stephan Gerhold Reviewed-by: Srinivas Kandagatla Cc: Srinivas Kandagatla Link: https://lore.kernel.org/r/20200415081159.1098-1-stephan@gerhold.net Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/qcom,q6adm.txt | 2 +- .../devicetree/bindings/sound/qcom,q6afe.txt | 46 +++++++++---------- .../devicetree/bindings/sound/qcom,q6asm.txt | 7 ++- .../devicetree/bindings/sound/qcom,q6core.txt | 2 +- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,q6adm.txt b/Documentation/devicetree/bindings/sound/qcom,q6adm.txt index bbae426cdfb1..15c353a20de8 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6adm.txt +++ b/Documentation/devicetree/bindings/sound/qcom,q6adm.txt @@ -29,7 +29,7 @@ used by the apr service device. Definition: Must be 0 = EXAMPLE -q6adm@8 { +apr-service@8 { compatible = "qcom,q6adm"; reg = ; q6routing: routing { diff --git a/Documentation/devicetree/bindings/sound/qcom,q6afe.txt b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt index d74888b9f1bb..4916dd6a0896 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6afe.txt +++ b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt @@ -100,7 +100,7 @@ configuration of each dai. Must contain the following properties. = EXAMPLE -q6afe@4 { +apr-service@4 { compatible = "qcom,q6afe"; reg = ; @@ -110,12 +110,12 @@ q6afe@4 { #address-cells = <1>; #size-cells = <0>; - hdmi@1 { - reg = <1>; + dai@1 { + reg = ; }; - tdm@24 { - reg = <24>; + dai@24 { + reg = ; qcom,tdm-sync-mode = <1>: qcom,tdm-sync-src = <1>; qcom,tdm-data-out = <0>; @@ -125,8 +125,8 @@ q6afe@4 { }; - tdm@25 { - reg = <25>; + dai@25 { + reg = ; qcom,tdm-sync-mode = <1>: qcom,tdm-sync-src = <1>; qcom,tdm-data-out = <0>; @@ -135,43 +135,43 @@ q6afe@4 { qcom,tdm-data-align = <0>; }; - prim-mi2s-rx@16 { - reg = <16>; + dai@16 { + reg = ; qcom,sd-lines = <0 2>; }; - prim-mi2s-tx@17 { - reg = <17>; + dai@17 { + reg = ; qcom,sd-lines = <1>; }; - sec-mi2s-rx@18 { - reg = <18>; + dai@18 { + reg = ; qcom,sd-lines = <0 3>; }; - sec-mi2s-tx@19 { - reg = <19>; + dai@19 { + reg = ; qcom,sd-lines = <1>; }; - tert-mi2s-rx@20 { - reg = <20>; + dai@20 { + reg = ; qcom,sd-lines = <1 3>; }; - tert-mi2s-tx@21 { - reg = <21>; + dai@21 { + reg = ; qcom,sd-lines = <0>; }; - quat-mi2s-rx@22 { - reg = <22>; + dai@22 { + reg = ; qcom,sd-lines = <0>; }; - quat-mi2s-tx@23 { - reg = <23>; + dai@23 { + reg = ; qcom,sd-lines = <1>; }; }; diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt index 9f5378c51686..6b9a88d0ea3f 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt +++ b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt @@ -51,13 +51,16 @@ configuration of each dai. Must contain the following properties. = EXAMPLE -q6asm@7 { +apr-service@7 { compatible = "qcom,q6asm"; reg = ; q6asmdai: dais { compatible = "qcom,q6asm-dais"; + #address-cells = <1>; + #size-cells = <0>; #sound-dai-cells = <1>; - mm@0 { + + dai@0 { reg = <0>; direction = <2>; is-compress-dai; diff --git a/Documentation/devicetree/bindings/sound/qcom,q6core.txt b/Documentation/devicetree/bindings/sound/qcom,q6core.txt index 7f36ff8bec18..5cd4cc9b1fde 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6core.txt +++ b/Documentation/devicetree/bindings/sound/qcom,q6core.txt @@ -15,7 +15,7 @@ used by the apr service device. example "qcom,q6core-v2.0" = EXAMPLE -q6core@3 { +apr-service@3 { compatible = "qcom,q6core"; reg = ; }; From b938b25f49cdb47397b0215b69cdd5251b4b2f8b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 16 Apr 2020 12:30:58 +0200 Subject: [PATCH 065/428] ASoC: Fix misspellings of "Analog Devices" According to https://www.analog.com/, the company name is spelled "Analog Devices". Signed-off-by: Geert Uytterhoeven Reviewed-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200416103058.15269-7-geert+renesas@glider.be Signed-off-by: Mark Brown --- sound/soc/codecs/ad1980.c | 2 +- sound/soc/codecs/ad73311.c | 2 +- sound/soc/codecs/wm8782.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index c4414c725c1f..43b1337bac37 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -2,7 +2,7 @@ /* * ad1980.c -- ALSA Soc AD1980 codec support * - * Copyright: Analog Device Inc. + * Copyright: Analog Devices Inc. * Author: Roy Huang * Cliff Cai */ diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index 10daf61f0294..b98bf19f594e 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c @@ -2,7 +2,7 @@ /* * ad73311.c -- ALSA Soc AD73311 codec support * - * Copyright: Analog Device Inc. + * Copyright: Analog Devices Inc. * Author: Cliff Cai */ diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c index aa5577e364d0..f89855c616eb 100644 --- a/sound/soc/codecs/wm8782.c +++ b/sound/soc/codecs/wm8782.c @@ -7,7 +7,7 @@ * Author: Johannes Stezenbach * * based on ad73311.c - * Copyright: Analog Device Inc. + * Copyright: Analog Devices Inc. * Author: Cliff Cai */ From aa08ff0f345ef68829bab30ddb5a23e9d99301b7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 16 Apr 2020 12:30:57 +0200 Subject: [PATCH 066/428] ALSA: Fix misspellings of "Analog Devices" According to https://www.analog.com/, the company name is spelled "Analog Devices". Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200416103058.15269-6-geert+renesas@glider.be Signed-off-by: Takashi Iwai --- sound/isa/ad1816a/ad1816a.c | 2 +- sound/pci/ac97/ac97_patch.c | 2 +- sound/pci/hda/Kconfig | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index ce4c8ba2fa98..ca18fe3ff8a5 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -54,7 +54,7 @@ MODULE_PARM_DESC(clockfreq, "Clock frequency for ad1816a driver (default = 0).") static const struct pnp_card_device_id snd_ad1816a_pnpids[] = { /* Analog Devices AD1815 */ { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } }, - /* Analog Device AD1816? */ + /* Analog Devices AD1816? */ { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, /* Analog Devices AD1816A - added by Kenneth Platz */ { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index ebf926728c5f..45ef0f52ec55 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1356,7 +1356,7 @@ static int patch_cx20551(struct snd_ac97 *ac97) } /* - * Analog Device AD18xx, AD19xx codecs + * Analog Devices AD18xx, AD19xx codecs */ #ifdef CONFIG_PM static void ad18xx_resume(struct snd_ac97 *ac97) diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index e1d3082a4fe9..7ba542e45a3d 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -99,10 +99,10 @@ comment "Set to Y if you want auto-loading the codec driver" depends on SND_HDA=y && SND_HDA_CODEC_REALTEK=m config SND_HDA_CODEC_ANALOG - tristate "Build Analog Device HD-audio codec support" + tristate "Build Analog Devices HD-audio codec support" select SND_HDA_GENERIC help - Say Y or M here to include Analog Device HD-audio codec support in + Say Y or M here to include Analog Devices HD-audio codec support in snd-hda-intel driver, such as AD1986A. comment "Set to Y if you want auto-loading the codec driver" From 8ec7d6043263ecf250b9b7c0dd8ade899487538a Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 30 Mar 2020 21:45:20 +0200 Subject: [PATCH 067/428] ASoC: Intel: haswell: Power transition refactor Update D0 <-> D3 sequence to correctly transition hardware and DSP core from and to D3. On top of that, set SHIM registers to their recommended defaults during D0 and D3 proceduces as HW does not reset registers for us. Connected to: [alsa-devel][BUG] bdw-rt5650 DSP boot timeout https://mailman.alsa-project.org/pipermail/alsa-devel/2019-July/153098.html Github issue ticket reference: https://github.com/thesofproject/linux/pull/1842 Tested on: - BDW-Y RVP with rt286 - SAMUS with rt5677 Proposed solution (both in July 2019 and on github): 'Revert "ASoC: Intel: Work around to fix HW d3 potential crash issue"' is NAKed as it only covers the problem up and actually brings back the undefined behavior: some registers (e.g.: APLLSE) are describing LPT offsets rather than WPT ones. In consequence, during power-transitions driver issues incorrect writes and leaves the regs of interest alone. Existing patch - the non-revert - does not resolve the HW D3 issue at all as it ignores the recommended sequence and does not initialize hardware registers as expected. And thus, leaving things as are is also unacceptable. Signed-off-by: Cezary Rojewski Tested-by: Ross Zwisler Link: https://lore.kernel.org/r/20200330194520.13253-1-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/haswell/sst-haswell-dsp.c | 185 ++++++++++++---------- 1 file changed, 104 insertions(+), 81 deletions(-) diff --git a/sound/soc/intel/haswell/sst-haswell-dsp.c b/sound/soc/intel/haswell/sst-haswell-dsp.c index 88c3f63bded9..de80e19454c1 100644 --- a/sound/soc/intel/haswell/sst-haswell-dsp.c +++ b/sound/soc/intel/haswell/sst-haswell-dsp.c @@ -243,45 +243,92 @@ static irqreturn_t hsw_irq(int irq, void *context) return ret; } +#define CSR_DEFAULT_VALUE 0x8480040E +#define ISC_DEFAULT_VALUE 0x0 +#define ISD_DEFAULT_VALUE 0x0 +#define IMC_DEFAULT_VALUE 0x7FFF0003 +#define IMD_DEFAULT_VALUE 0x7FFF0003 +#define IPCC_DEFAULT_VALUE 0x0 +#define IPCD_DEFAULT_VALUE 0x0 +#define CLKCTL_DEFAULT_VALUE 0x7FF +#define CSR2_DEFAULT_VALUE 0x0 +#define LTR_CTRL_DEFAULT_VALUE 0x0 +#define HMD_CTRL_DEFAULT_VALUE 0x0 + +static void hsw_set_shim_defaults(struct sst_dsp *sst) +{ + sst_dsp_shim_write_unlocked(sst, SST_CSR, CSR_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_ISRX, ISC_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_ISRD, ISD_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_IMRX, IMC_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_IMRD, IMD_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_IPCX, IPCC_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_IPCD, IPCD_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_CLKCTL, CLKCTL_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_CSR2, CSR2_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_LTRC, LTR_CTRL_DEFAULT_VALUE); + sst_dsp_shim_write_unlocked(sst, SST_HMDC, HMD_CTRL_DEFAULT_VALUE); +} + +/* all clock-gating minus DCLCGE and DTCGE */ +#define SST_VDRTCL2_CG_OTHER 0xB7D + static void hsw_set_dsp_D3(struct sst_dsp *sst) { - u32 val; u32 reg; - /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */ + /* disable clock core gating */ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); - reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE); + reg &= ~(SST_VDRTCL2_DCLCGE); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); - /* enable power gating and switch off DRAM & IRAM blocks */ - val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); - val |= SST_VDRTCL0_DSRAMPGE_MASK | - SST_VDRTCL0_ISRAMPGE_MASK; - val &= ~(SST_VDRTCL0_D3PGD | SST_VDRTCL0_D3SRAMPGD); - writel(val, sst->addr.pci_cfg + SST_VDRTCTL0); + /* stall, reset and set 24MHz XOSC */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, + SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST, + SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST); - /* switch off audio PLL */ - val = readl(sst->addr.pci_cfg + SST_VDRTCTL2); - val |= SST_VDRTCL2_APLLSE_MASK; - writel(val, sst->addr.pci_cfg + SST_VDRTCTL2); + /* DRAM power gating all */ + reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); + reg |= SST_VDRTCL0_ISRAMPGE_MASK | + SST_VDRTCL0_DSRAMPGE_MASK; + reg &= ~(SST_VDRTCL0_D3SRAMPGD); + reg |= SST_VDRTCL0_D3PGD; + writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0); + udelay(50); - /* disable MCLK(clkctl.smos = 0) */ + /* PLL shutdown enable */ + reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); + reg |= SST_VDRTCL2_APLLSE_MASK; + writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); + + /* disable MCLK */ sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL, - SST_CLKCTL_MASK, 0); + SST_CLKCTL_MASK, 0); - /* Set D3 state, delay 50 us */ - val = readl(sst->addr.pci_cfg + SST_PMCS); - val |= SST_PMCS_PS_MASK; - writel(val, sst->addr.pci_cfg + SST_PMCS); - udelay(50); - - /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */ + /* switch clock gating */ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); - reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE; + reg |= SST_VDRTCL2_CG_OTHER; + reg &= ~(SST_VDRTCL2_DTCGE); + writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); + /* enable DTCGE separatelly */ + reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); + reg |= SST_VDRTCL2_DTCGE; writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); + /* set shim defaults */ + hsw_set_shim_defaults(sst); + + /* set D3 */ + reg = readl(sst->addr.pci_cfg + SST_PMCS); + reg |= SST_PMCS_PS_MASK; + writel(reg, sst->addr.pci_cfg + SST_PMCS); udelay(50); + /* enable clock core gating */ + reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); + reg |= SST_VDRTCL2_DCLCGE; + writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); + udelay(50); } static void hsw_reset(struct sst_dsp *sst) @@ -299,75 +346,62 @@ static void hsw_reset(struct sst_dsp *sst) SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL); } +/* recommended CSR state for power-up */ +#define SST_CSR_D0_MASK (0x18A09C0C | SST_CSR_DCS_MASK) + static int hsw_set_dsp_D0(struct sst_dsp *sst) { - int tries = 10; - u32 reg, fw_dump_bit; + u32 reg; - /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */ + /* disable clock core gating */ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); - reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE); + reg &= ~(SST_VDRTCL2_DCLCGE); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); - /* Disable D3PG (VDRTCTL0.D3PGD = 1) */ - reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); - reg |= SST_VDRTCL0_D3PGD; - writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0); + /* switch clock gating */ + reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); + reg |= SST_VDRTCL2_CG_OTHER; + reg &= ~(SST_VDRTCL2_DTCGE); + writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); - /* Set D0 state */ + /* set D0 */ reg = readl(sst->addr.pci_cfg + SST_PMCS); - reg &= ~SST_PMCS_PS_MASK; + reg &= ~(SST_PMCS_PS_MASK); writel(reg, sst->addr.pci_cfg + SST_PMCS); - /* check that ADSP shim is enabled */ - while (tries--) { - reg = readl(sst->addr.pci_cfg + SST_PMCS) & SST_PMCS_PS_MASK; - if (reg == 0) - goto finish; + /* DRAM power gating none */ + reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); + reg &= ~(SST_VDRTCL0_ISRAMPGE_MASK | + SST_VDRTCL0_DSRAMPGE_MASK); + reg |= SST_VDRTCL0_D3SRAMPGD; + reg |= SST_VDRTCL0_D3PGD; + writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0); + mdelay(10); - msleep(1); - } + /* set shim defaults */ + hsw_set_shim_defaults(sst); - return -ENODEV; - -finish: - /* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */ - sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, - SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0); - - /* stall DSP core, set clk to 192/96Mhz */ - sst_dsp_shim_update_bits_unlocked(sst, - SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK, - SST_CSR_STALL | SST_CSR_DCS(4)); - - /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */ + /* restore MCLK */ sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL, - SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0, - SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0); + SST_CLKCTL_MASK, SST_CLKCTL_MASK); - /* Stall and reset core, set CSR */ - hsw_reset(sst); - - /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */ + /* PLL shutdown disable */ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); - reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE; + reg &= ~(SST_VDRTCL2_APLLSE_MASK); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, + SST_CSR_D0_MASK, SST_CSR_SBCS0 | SST_CSR_SBCS1 | + SST_CSR_STALL | SST_CSR_DCS(4)); udelay(50); - /* switch on audio PLL */ + /* enable clock core gating */ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); - reg &= ~SST_VDRTCL2_APLLSE_MASK; + reg |= SST_VDRTCL2_DCLCGE; writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); - /* set default power gating control, enable power gating control for all blocks. that is, - can't be accessed, please enable each block before accessing. */ - reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); - reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK; - /* for D0, always enable the block(DSRAM[0]) used for FW dump */ - fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT; - writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0); - + /* clear reset */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_RST, 0); /* disable DMA finish function for SSP0 & SSP1 */ sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1, @@ -384,12 +418,6 @@ finish: sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY | SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0); - /* clear IPC registers */ - sst_dsp_shim_write(sst, SST_IPCX, 0x0); - sst_dsp_shim_write(sst, SST_IPCD, 0x0); - sst_dsp_shim_write(sst, 0x80, 0x6); - sst_dsp_shim_write(sst, 0xe0, 0x300a); - return 0; } @@ -415,11 +443,6 @@ static void hsw_sleep(struct sst_dsp *sst) { dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n"); - /* put DSP into reset and stall */ - sst_dsp_shim_update_bits(sst, SST_CSR, - SST_CSR_24MHZ_LPCS | SST_CSR_RST | SST_CSR_STALL, - SST_CSR_RST | SST_CSR_STALL | SST_CSR_24MHZ_LPCS); - hsw_set_dsp_D3(sst); dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n"); } From 093b8494f2992e58c2bef6fc26c7e11464ad415a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 19 Apr 2020 23:21:34 +0200 Subject: [PATCH 068/428] ALSA: usb-audio: Print more information in stream proc files For more debug and usability information, add the entry showing the DSD raw states and the channel mapping in each stream proc file. Link: https://lore.kernel.org/r/20200419212134.14200-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/proc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index 4174ad11fca6..5a36e192ebb0 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -54,6 +54,38 @@ void snd_usb_audio_create_proc(struct snd_usb_audio *chip) proc_audio_usbid_read); } +static const char * const channel_labels[] = { + [SNDRV_CHMAP_NA] = "N/A", + [SNDRV_CHMAP_MONO] = "MONO", + [SNDRV_CHMAP_FL] = "FL", + [SNDRV_CHMAP_FR] = "FR", + [SNDRV_CHMAP_FC] = "FC", + [SNDRV_CHMAP_LFE] = "LFE", + [SNDRV_CHMAP_RL] = "RL", + [SNDRV_CHMAP_RR] = "RR", + [SNDRV_CHMAP_FLC] = "FLC", + [SNDRV_CHMAP_FRC] = "FRC", + [SNDRV_CHMAP_RC] = "RC", + [SNDRV_CHMAP_SL] = "SL", + [SNDRV_CHMAP_SR] = "SR", + [SNDRV_CHMAP_TC] = "TC", + [SNDRV_CHMAP_TFL] = "TFL", + [SNDRV_CHMAP_TFC] = "TFC", + [SNDRV_CHMAP_TFR] = "TFR", + [SNDRV_CHMAP_TRL] = "TRL", + [SNDRV_CHMAP_TRC] = "TRC", + [SNDRV_CHMAP_TRR] = "TRR", + [SNDRV_CHMAP_TFLC] = "TFLC", + [SNDRV_CHMAP_TFRC] = "TFRC", + [SNDRV_CHMAP_LLFE] = "LLFE", + [SNDRV_CHMAP_RLFE] = "RLFE", + [SNDRV_CHMAP_TSL] = "TSL", + [SNDRV_CHMAP_TSR] = "TSR", + [SNDRV_CHMAP_BC] = "BC", + [SNDRV_CHMAP_RLC] = "RLC", + [SNDRV_CHMAP_RRC] = "RRC", +}; + /* * proc interface for list the supported pcm formats */ @@ -97,6 +129,27 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s snd_iprintf(buffer, " Data packet interval: %d us\n", 125 * (1 << fp->datainterval)); snd_iprintf(buffer, " Bits: %d\n", fp->fmt_bits); + + if (fp->dsd_raw) + snd_iprintf(buffer, " DSD raw: DOP=%d, bitrev=%d\n", + fp->dsd_dop, fp->dsd_bitrev); + + if (fp->chmap) { + const struct snd_pcm_chmap_elem *map = fp->chmap; + int c; + + snd_iprintf(buffer, " Channel map:"); + for (c = 0; c < map->channels; c++) { + if (map->map[c] >= sizeof(channel_labels) || + !channel_labels[map->map[c]]) + snd_iprintf(buffer, " --"); + else + snd_iprintf(buffer, " %s", + channel_labels[map->map[c]]); + } + snd_iprintf(buffer, "\n"); + } + // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); } From 91e475b5e810c7e0d6346e58017507d66a23f526 Mon Sep 17 00:00:00 2001 From: Wei Li Date: Tue, 21 Apr 2020 04:24:09 +0800 Subject: [PATCH 069/428] ASoC: wm89xx: Fix build errors caused by I2C dependency When I2C=m, SND_SOC_WM8900=y, SND_SOC_WM8988=y, SND_SOC_WM8995=y: sound/soc/codecs/wm8900.o: In function `wm8900_i2c_probe': wm8900.c:(.text+0xa16): undefined reference to `__devm_regmap_init_i2c' sound/soc/codecs/wm8900.o: In function `wm8900_modinit': wm8900.c:(.init.text+0xb): undefined reference to `i2c_register_driver' sound/soc/codecs/wm8900.o: In function `wm8900_exit': wm8900.c:(.exit.text+0x8): undefined reference to `i2c_del_driver' sound/soc/codecs/wm8988.o: In function `wm8988_i2c_probe': wm8988.c:(.text+0x86b): undefined reference to `__devm_regmap_init_i2c' sound/soc/codecs/wm8988.o: In function `wm8988_modinit': wm8988.c:(.init.text+0xb): undefined reference to `i2c_register_driver' sound/soc/codecs/wm8988.o: In function `wm8988_exit': wm8988.c:(.exit.text+0x8): undefined reference to `i2c_del_driver' sound/soc/codecs/wm8995.o: In function `wm8995_i2c_probe': wm8995.c:(.text+0x1b5b): undefined reference to `__devm_regmap_init_i2c' sound/soc/codecs/wm8995.o: In function `wm8995_modinit': wm8995.c:(.init.text+0xb): undefined reference to `i2c_register_driver' sound/soc/codecs/wm8995.o: In function `wm8995_exit': wm8995.c:(.exit.text+0x8): undefined reference to `i2c_del_driver' As these drivers support I2C and SPI, we add the SND_SOC_I2C_AND_SPI dependency to solve it. Fixes: ea00d95200d02 ("ASoC: Use imply for SND_SOC_ALL_CODECS") Reported-by: Hulk Robot Signed-off-by: Wei Li Link: https://lore.kernel.org/r/20200420202410.47327-2-liwei391@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index e6a0c5d05fa5..e60e0b6a689c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1525,6 +1525,7 @@ config SND_SOC_WM8804_SPI config SND_SOC_WM8900 tristate + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8903 tristate "Wolfson Microelectronics WM8903 CODEC" @@ -1576,6 +1577,7 @@ config SND_SOC_WM8985 config SND_SOC_WM8988 tristate + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8990 tristate @@ -1594,6 +1596,7 @@ config SND_SOC_WM8994 config SND_SOC_WM8995 tristate + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8996 tristate From c1c050ee74d67aeb879fd38e3a07139d7fdb79f4 Mon Sep 17 00:00:00 2001 From: Wei Li Date: Tue, 21 Apr 2020 04:24:10 +0800 Subject: [PATCH 070/428] ASoC: Fix wrong dependency of da7210 and wm8983 As these two drivers support I2C and SPI, we should add the SND_SOC_I2C_AND_SPI dependency instead. Fixes: ce0c97f8a2936 ("ASoC: Fix SND_SOC_ALL_CODECS imply SPI fallout") Signed-off-by: Wei Li Link: https://lore.kernel.org/r/20200420202410.47327-3-liwei391@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index e60e0b6a689c..d0fec1b90256 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -717,7 +717,7 @@ config SND_SOC_L3 config SND_SOC_DA7210 tristate - depends on I2C + depends on SND_SOC_I2C_AND_SPI config SND_SOC_DA7213 tristate "Dialog DA7213 CODEC" @@ -1569,7 +1569,7 @@ config SND_SOC_WM8978 config SND_SOC_WM8983 tristate - depends on I2C + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8985 tristate "Wolfson Microelectronics WM8985 and WM8758 codec driver" From 4eb542cc88c1c255a70e745b12ae913cd3edb535 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:01:01 +0900 Subject: [PATCH 071/428] soundwire: intel: use asoc_rtd_to_cpu() / asoc_rtd_to_codec() macro for DAI pointer Now ALSA SoC needs to use asoc_rtd_to_codec(), otherwise, it will be compile error. Signed-off-by: Kuninori Morimoto Acked-By: Vinod Koul Link: https://lore.kernel.org/r/87y2qqvdxu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- drivers/soundwire/intel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 3c83e76c6bf9..ed8d576bf5dc 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -669,11 +669,11 @@ static int sdw_stream_setup(struct snd_pcm_substream *substream, /* Set stream pointer on all CODEC DAIs */ for (i = 0; i < rtd->num_codecs; i++) { - ret = snd_soc_dai_set_sdw_stream(rtd->codec_dais[i], sdw_stream, + ret = snd_soc_dai_set_sdw_stream(asoc_rtd_to_codec(rtd, i), sdw_stream, substream->stream); if (ret < 0) { dev_err(dai->dev, "failed to set stream pointer on codec dai %s", - rtd->codec_dais[i]->name); + asoc_rtd_to_codec(rtd, i)->name); goto release_stream; } } From 629ba12e9998f344389e096a7cec6286c86ed7ab Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Mon, 23 Mar 2020 10:49:24 +0800 Subject: [PATCH 072/428] ASoC: Intel: boards: split woofer and tweeter support Support Woofer stereo speakers by default and optionally Tweeter stereo speakers with a DMI quirk Signed-off-by: Mac Chiang Link: https://lore.kernel.org/r/1584931764-2778-1-git-send-email-mac.chiang@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cml_rt1011_rt5682.c | 222 +++++++++++++++++---- 1 file changed, 180 insertions(+), 42 deletions(-) diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index 8167b2977e1d..da6fefaf6785 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -30,6 +30,36 @@ #define CML_RT5682_CODEC_DAI "rt5682-aif1" #define NAME_SIZE 32 +#define SOF_RT1011_SPEAKER_WL BIT(0) +#define SOF_RT1011_SPEAKER_WR BIT(1) +#define SOF_RT1011_SPEAKER_TL BIT(2) +#define SOF_RT1011_SPEAKER_TR BIT(3) +#define SPK_CH 4 + +/* Default: Woofer speakers */ +static unsigned long sof_rt1011_quirk = SOF_RT1011_SPEAKER_WL | + SOF_RT1011_SPEAKER_WR; + +static int sof_rt1011_quirk_cb(const struct dmi_system_id *id) +{ + sof_rt1011_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id sof_rt1011_quirk_table[] = { + { + .callback = sof_rt1011_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_PRODUCT_NAME, "Helios"), + }, + .driver_data = (void *)(SOF_RT1011_SPEAKER_WL | SOF_RT1011_SPEAKER_WR | + SOF_RT1011_SPEAKER_TL | SOF_RT1011_SPEAKER_TR), + }, + { + } +}; + static struct snd_soc_jack hdmi_jack[3]; struct hdmi_pcm { @@ -48,15 +78,16 @@ struct card_private { static const struct snd_kcontrol_new cml_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("TL Ext Spk"), - SOC_DAPM_PIN_SWITCH("TR Ext Spk"), SOC_DAPM_PIN_SWITCH("WL Ext Spk"), SOC_DAPM_PIN_SWITCH("WR Ext Spk"), }; +static const struct snd_kcontrol_new cml_rt1011_tt_controls[] = { + SOC_DAPM_PIN_SWITCH("TL Ext Spk"), + SOC_DAPM_PIN_SWITCH("TR Ext Spk"), +}; + static const struct snd_soc_dapm_widget cml_rt1011_rt5682_widgets[] = { - SND_SOC_DAPM_SPK("TL Ext Spk", NULL), - SND_SOC_DAPM_SPK("TR Ext Spk", NULL), SND_SOC_DAPM_SPK("WL Ext Spk", NULL), SND_SOC_DAPM_SPK("WR Ext Spk", NULL), SND_SOC_DAPM_HP("Headphone Jack", NULL), @@ -64,10 +95,13 @@ static const struct snd_soc_dapm_widget cml_rt1011_rt5682_widgets[] = { SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; +static const struct snd_soc_dapm_widget cml_rt1011_tt_widgets[] = { + SND_SOC_DAPM_SPK("TL Ext Spk", NULL), + SND_SOC_DAPM_SPK("TR Ext Spk", NULL), +}; + static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = { - /*speaker*/ - {"TL Ext Spk", NULL, "TL SPO"}, - {"TR Ext Spk", NULL, "TR SPO"}, + /*WL/WR speaker*/ {"WL Ext Spk", NULL, "WL SPO"}, {"WR Ext Spk", NULL, "WR SPO"}, @@ -82,6 +116,12 @@ static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = { {"DMic", NULL, "SoC DMIC"}, }; +static const struct snd_soc_dapm_route cml_rt1011_tt_map[] = { + /*TL/TR speaker*/ + {"TL Ext Spk", NULL, "TL SPO" }, + {"TR Ext Spk", NULL, "TR SPO" }, +}; + static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) { struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); @@ -121,6 +161,35 @@ static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; }; +static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret = 0; + struct snd_soc_card *card = rtd->card; + + if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL | + SOF_RT1011_SPEAKER_TR)) { + + ret = snd_soc_add_card_controls(card, cml_rt1011_tt_controls, + ARRAY_SIZE(cml_rt1011_tt_controls)); + if (ret) + return ret; + + ret = snd_soc_dapm_new_controls(&card->dapm, + cml_rt1011_tt_widgets, + ARRAY_SIZE(cml_rt1011_tt_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(&card->dapm, cml_rt1011_tt_map, + ARRAY_SIZE(cml_rt1011_tt_map)); + + if (ret) + return ret; + } + + return ret; +} + static int cml_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -191,30 +260,38 @@ static int cml_rt1011_hw_params(struct snd_pcm_substream *substream, * The feedback is captured for each codec individually. * Hence all 4 codecs use 1 Tx slot each for feedback. */ - if (!strcmp(codec_dai->component->name, "i2c-10EC1011:00")) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x4, 0x1, 4, 24); - if (ret < 0) - break; + if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_WL | + SOF_RT1011_SPEAKER_WR)) { + if (!strcmp(codec_dai->component->name, "i2c-10EC1011:00")) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, + 0x4, 0x1, 4, 24); + if (ret < 0) + break; + } + + if (!strcmp(codec_dai->component->name, "i2c-10EC1011:01")) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, + 0x8, 0x2, 4, 24); + if (ret < 0) + break; + } } - if (!strcmp(codec_dai->component->name, "i2c-10EC1011:02")) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x1, 0x1, 4, 24); - if (ret < 0) - break; - } - /* TDM Rx slot 2 is used for Right Woofer & Tweeters pair */ - if (!strcmp(codec_dai->component->name, "i2c-10EC1011:01")) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x8, 0x2, 4, 24); - if (ret < 0) - break; - } - if (!strcmp(codec_dai->component->name, "i2c-10EC1011:03")) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x2, 0x2, 4, 24); - if (ret < 0) - break; + + if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL | + SOF_RT1011_SPEAKER_TR)) { + if (!strcmp(codec_dai->component->name, "i2c-10EC1011:02")) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, + 0x1, 0x1, 4, 24); + if (ret < 0) + break; + } + + if (!strcmp(codec_dai->component->name, "i2c-10EC1011:03")) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, + 0x2, 0x2, 4, 24); + if (ret < 0) + break; + } } } if (ret < 0) @@ -302,9 +379,7 @@ SND_SOC_DAILINK_DEF(ssp1_pin, SND_SOC_DAILINK_DEF(ssp1_codec, DAILINK_COMP_ARRAY( /* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI), - /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI), - /* TL */ COMP_CODEC("i2c-10EC1011:02", CML_RT1011_CODEC_DAI), - /* TR */ COMP_CODEC("i2c-10EC1011:03", CML_RT1011_CODEC_DAI))); + /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI))); SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); @@ -398,6 +473,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .dpcm_playback = 1, .dpcm_capture = 1, /* Capture stream provides Feedback */ .no_pcm = 1, + .init = cml_rt1011_spk_init, .ops = &cml_rt1011_ops, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, @@ -412,14 +488,6 @@ static struct snd_soc_codec_conf rt1011_conf[] = { .dlc = COMP_CODEC_CONF("i2c-10EC1011:01"), .name_prefix = "WR", }, - { - .dlc = COMP_CODEC_CONF("i2c-10EC1011:02"), - .name_prefix = "TL", - }, - { - .dlc = COMP_CODEC_CONF("i2c-10EC1011:03"), - .name_prefix = "TR", - }, }; /* Cometlake audio machine driver for RT1011 and RT5682 */ @@ -441,10 +509,12 @@ static struct snd_soc_card snd_soc_card_cml = { static int snd_cml_rt1011_probe(struct platform_device *pdev) { + struct snd_soc_dai_link_component *rt1011_dais_components; + struct snd_soc_codec_conf *rt1011_dais_confs; struct card_private *ctx; struct snd_soc_acpi_mach *mach; const char *platform_name; - int ret; + int ret, i; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -455,6 +525,73 @@ static int snd_cml_rt1011_probe(struct platform_device *pdev) snd_soc_card_cml.dev = &pdev->dev; platform_name = mach->mach_params.platform; + dmi_check_system(sof_rt1011_quirk_table); + + dev_info(&pdev->dev, "sof_rt1011_quirk = %lx\n", sof_rt1011_quirk); + + if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL | + SOF_RT1011_SPEAKER_TR)) { + rt1011_dais_confs = devm_kzalloc(&pdev->dev, + sizeof(struct snd_soc_codec_conf) * + SPK_CH, GFP_KERNEL); + + if (!rt1011_dais_confs) + return -ENOMEM; + + rt1011_dais_components = devm_kzalloc(&pdev->dev, + sizeof(struct snd_soc_dai_link_component) * + SPK_CH, GFP_KERNEL); + + if (!rt1011_dais_components) + return -ENOMEM; + + for (i = 0; i < SPK_CH; i++) { + rt1011_dais_confs[i].dlc.name = devm_kasprintf(&pdev->dev, + GFP_KERNEL, + "i2c-10EC1011:0%d", + i); + + if (!rt1011_dais_confs[i].dlc.name) + return -ENOMEM; + + switch (i) { + case 0: + rt1011_dais_confs[i].name_prefix = "WL"; + break; + case 1: + rt1011_dais_confs[i].name_prefix = "WR"; + break; + case 2: + rt1011_dais_confs[i].name_prefix = "TL"; + break; + case 3: + rt1011_dais_confs[i].name_prefix = "TR"; + break; + default: + return -EINVAL; + } + rt1011_dais_components[i].name = devm_kasprintf(&pdev->dev, + GFP_KERNEL, + "i2c-10EC1011:0%d", + i); + if (!rt1011_dais_components[i].name) + return -ENOMEM; + + rt1011_dais_components[i].dai_name = CML_RT1011_CODEC_DAI; + } + + snd_soc_card_cml.codec_conf = rt1011_dais_confs; + snd_soc_card_cml.num_configs = SPK_CH; + + for (i = 0; i < ARRAY_SIZE(cml_rt1011_rt5682_dailink); i++) { + if (!strcmp(cml_rt1011_rt5682_dailink[i].codecs->dai_name, + CML_RT1011_CODEC_DAI)) { + cml_rt1011_rt5682_dailink[i].codecs = rt1011_dais_components; + cml_rt1011_rt5682_dailink[i].num_codecs = SPK_CH; + } + } + } + /* set platform name for each dailink */ ret = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cml, platform_name); @@ -482,5 +619,6 @@ MODULE_DESCRIPTION("Cometlake Audio Machine driver - RT1011 and RT5682 in I2S mo MODULE_AUTHOR("Naveen Manohar "); MODULE_AUTHOR("Sathya Prakash M R "); MODULE_AUTHOR("Shuming Fan "); +MODULE_AUTHOR("Mac Chiang "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:cml_rt1011_rt5682"); From 4f05b5c62d248d6a25edcd13795001fb5eaa2080 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Mon, 20 Apr 2020 12:28:33 +0800 Subject: [PATCH 073/428] ASoC: wcd934x: remove unnecessary comparisons to bool Fix the following coccicheck warning: sound/soc/codecs/wcd934x.c:3881:8-17: WARNING: Comparison of 0/1 to bool variable Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200420042833.19116-1-yanaijie@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 5269857e2746..4d6b4992a940 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -3878,7 +3878,7 @@ static u32 wcd934x_get_dmic_sample_rate(struct snd_soc_component *comp, u16 adc_mux_ctl_reg, tx_fs_reg; u32 dmic_fs; - while (dec_found == 0 && adc_mux_index < WCD934X_MAX_VALID_ADC_MUX) { + while (!dec_found && adc_mux_index < WCD934X_MAX_VALID_ADC_MUX) { if (adc_mux_index < 4) { adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 + (adc_mux_index * 2); From 0eb0674616b03da3d636134a8367eed284732b65 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Mon, 20 Apr 2020 12:28:47 +0800 Subject: [PATCH 074/428] ASoC: wcd9335: remove unneeded semicolon Fix the following coccicheck warning: sound/soc/codecs/wcd9335.c:2606:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3619:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:2849:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:2955:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:2988:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3960:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3776:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3924:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3355:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3832:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3079:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3089:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3232:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3878:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3578:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3728:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:1922:3-4: Unneeded semicolon sound/soc/codecs/wcd9335.c:1938:3-4: Unneeded semicolon sound/soc/codecs/wcd9335.c:1944:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:3144:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:2568:2-3: Unneeded semicolon sound/soc/codecs/wcd9335.c:2219:2-3: Unneeded semicolon Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200420042847.19206-1-yanaijie@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 700cc1212770..fb073f4dc7ed 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1919,7 +1919,7 @@ static int wcd9335_hw_params(struct snd_pcm_substream *substream, __func__, params_rate(params)); return -EINVAL; - }; + } ret = wcd9335_set_decimator_rate(dai, tx_fs_rate, params_rate(params)); @@ -1935,13 +1935,13 @@ static int wcd9335_hw_params(struct snd_pcm_substream *substream, dev_err(wcd->dev, "%s: Invalid format 0x%x\n", __func__, params_width(params)); return -EINVAL; - }; + } break; default: dev_err(wcd->dev, "Invalid stream type %d\n", substream->stream); return -EINVAL; - }; + } wcd->dai[dai->id].sconfig.rate = params_rate(params); wcd9335_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); @@ -2216,7 +2216,7 @@ static int wcd9335_set_compander(struct snd_kcontrol *kc, break; default: break; - }; + } return 0; } @@ -2565,7 +2565,7 @@ static int wcd9335_micbias_control(struct snd_soc_component *component, 0xC0, 0x00); } break; - }; + } return 0; } @@ -2603,7 +2603,7 @@ static int __wcd9335_codec_enable_micbias(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: wcd9335_micbias_control(comp, micb_num, MICB_DISABLE, true); break; - }; + } return 0; } @@ -2846,7 +2846,7 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(comp, tx_vol_ctl_reg, 0x10, 0x00); break; - }; + } out: kfree(wname); return ret; @@ -2952,7 +2952,7 @@ static int wcd9335_codec_enable_dmic(struct snd_soc_dapm_widget *w, dev_err(comp->dev, "%s: Invalid DMIC Selection\n", __func__); return -EINVAL; - }; + } switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -2985,7 +2985,7 @@ static int wcd9335_codec_enable_dmic(struct snd_soc_dapm_widget *w, dmic_rate_val << dmic_rate_shift); } break; - }; + } return 0; } @@ -3076,7 +3076,7 @@ static int wcd9335_codec_enable_mix_path(struct snd_soc_dapm_widget *w, dev_err(comp->dev, "%s: No gain register avail for %s\n", __func__, w->name); return 0; - }; + } switch (event) { case SND_SOC_DAPM_POST_PMU: @@ -3086,7 +3086,7 @@ static int wcd9335_codec_enable_mix_path(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMD: break; - }; + } return 0; } @@ -3141,7 +3141,7 @@ static u16 wcd9335_interp_get_primary_reg(u16 reg, u16 *ind) prim_int_reg = WCD9335_CDC_RX8_RX_PATH_CTL; *ind = 8; break; - }; + } return prim_int_reg; } @@ -3229,7 +3229,7 @@ static int wcd9335_codec_enable_prim_interpolator( wcd9335_codec_hd2_control(comp, prim_int_reg, event); } break; - }; + } return 0; } @@ -3352,7 +3352,7 @@ static int wcd9335_codec_enable_interpolator(struct snd_soc_dapm_widget *w, wcd9335_config_compander(comp, w->shift, event); wcd9335_codec_enable_prim_interpolator(comp, reg, event); break; - }; + } return 0; } @@ -3575,7 +3575,7 @@ static int wcd9335_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, ((hph_mode == CLS_H_LOHIFI) ? CLS_H_HIFI : hph_mode)); break; - }; + } return 0; } @@ -3616,7 +3616,7 @@ static int wcd9335_codec_ear_dac_event(struct snd_soc_dapm_widget *w, wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA, WCD_CLSH_STATE_EAR, CLS_H_NORMAL); break; - }; + } return 0; } @@ -3725,7 +3725,7 @@ static int wcd9335_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, WCD_CLSH_STATE_HPHR, ((hph_mode == CLS_H_LOHIFI) ? CLS_H_HIFI : hph_mode)); break; - }; + } return 0; } @@ -3773,7 +3773,7 @@ static int wcd9335_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, */ usleep_range(5000, 5500); break; - }; + } return 0; } @@ -3829,7 +3829,7 @@ static int wcd9335_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w, */ usleep_range(5000, 5500); break; - }; + } return 0; } @@ -3875,7 +3875,7 @@ static int wcd9335_codec_enable_rx_bias(struct snd_soc_dapm_widget *w, WCD9335_ANA_RX_BIAS_ENABLE_MASK, WCD9335_ANA_RX_BIAS_DISABLE); break; - }; + } return 0; } @@ -3921,7 +3921,7 @@ static int wcd9335_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, */ usleep_range(5000, 5500); break; - }; + } return 0; } @@ -3957,7 +3957,7 @@ static int wcd9335_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, usleep_range(5000, 5500); break; - }; + } return 0; } From e48e83d15bd98b15f7f9eb69f10e4ec595b3f69e Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Mon, 20 Apr 2020 12:29:11 +0800 Subject: [PATCH 075/428] ASoC: wcd934x: remove unneeded semicolon Fix the following coccicheck warning: sound/soc/codecs/wcd934x.c:3621:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:4270:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:4018:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:4043:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:3804:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:3866:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:3596:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:3542:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:3673:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:3723:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:2492:2-3: Unneeded semicolon sound/soc/codecs/wcd934x.c:1790:3-4: Unneeded semicolon sound/soc/codecs/wcd934x.c:1806:3-4: Unneeded semicolon sound/soc/codecs/wcd934x.c:1812:2-3: Unneeded semicolon Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200420042911.19379-1-yanaijie@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 4d6b4992a940..531b8b79e55f 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1787,7 +1787,7 @@ static int wcd934x_hw_params(struct snd_pcm_substream *substream, params_rate(params)); return -EINVAL; - }; + } ret = wcd934x_set_decimator_rate(dai, tx_fs_rate, params_rate(params)); @@ -1803,13 +1803,13 @@ static int wcd934x_hw_params(struct snd_pcm_substream *substream, dev_err(wcd->dev, "Invalid format 0x%x\n", params_width(params)); return -EINVAL; - }; + } break; default: dev_err(wcd->dev, "Invalid stream type %d\n", substream->stream); return -EINVAL; - }; + } wcd->dai[dai->id].sconfig.rate = params_rate(params); wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); @@ -2489,7 +2489,7 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, break; default: break; - }; + } return 0; } @@ -3539,7 +3539,7 @@ static int wcd934x_codec_enable_mix_path(struct snd_soc_dapm_widget *w, val += offset_val; snd_soc_component_write(comp, gain_reg, val); break; - }; + } return 0; } @@ -3593,7 +3593,7 @@ static int wcd934x_codec_enable_main_path(struct snd_soc_dapm_widget *w, snd_soc_component_write(comp, gain_reg, snd_soc_component_read32(comp, gain_reg)); break; - }; + } return 0; } @@ -3618,7 +3618,7 @@ static int wcd934x_codec_ear_dac_event(struct snd_soc_dapm_widget *w, wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA, WCD_CLSH_STATE_EAR, CLS_H_NORMAL); break; - }; + } return 0; } @@ -3670,7 +3670,7 @@ static int wcd934x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, break; default: break; - }; + } return 0; } @@ -3720,7 +3720,7 @@ static int wcd934x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, break; default: break; - }; + } return 0; } @@ -3801,7 +3801,7 @@ static int wcd934x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, */ usleep_range(20000, 20100); break; - }; + } return 0; } @@ -3863,7 +3863,7 @@ static int wcd934x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, */ usleep_range(20000, 20100); break; - }; + } return 0; } @@ -4015,7 +4015,7 @@ static int wcd934x_codec_enable_dmic(struct snd_soc_dapm_widget *w, dev_err(comp->dev, "%s: Invalid DMIC Selection\n", __func__); return -EINVAL; - }; + } switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -4040,7 +4040,7 @@ static int wcd934x_codec_enable_dmic(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(comp, dmic_clk_reg, dmic_clk_en, 0); break; - }; + } return 0; } @@ -4267,7 +4267,7 @@ static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w, WCD934X_DEC_PWR_LVL_MASK, WCD934X_DEC_PWR_LVL_DF); break; - }; + } out: kfree(wname); return ret; From 0de6db30ef79b391cedd749801a49c485d2daf4b Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 13 Jan 2020 23:24:17 -0800 Subject: [PATCH 076/428] ASoC: tegra: Use device managed resource APIs to get the clock tegra_asoc_utils uses clk_get() to get the clock and clk_put() to free them explicitly. This patch updates it to use device managed resource API devm_clk_get() so the clock will be automatically released and freed when the device is unbound and removes tegra_asoc_utils_fini() as its no longer needed. Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Reviewed-by: Sameer Pujar Signed-off-by: Sowjanya Komatineni Signed-off-by: Thierry Reding --- sound/soc/tegra/tegra_alc5632.c | 7 +----- sound/soc/tegra/tegra_asoc_utils.c | 34 ++++++------------------------ sound/soc/tegra/tegra_asoc_utils.h | 1 - sound/soc/tegra/tegra_max98090.c | 22 ++++++------------- sound/soc/tegra/tegra_rt5640.c | 22 ++++++------------- sound/soc/tegra/tegra_rt5677.c | 7 +----- sound/soc/tegra/tegra_sgtl5000.c | 7 +----- sound/soc/tegra/tegra_wm8753.c | 22 ++++++------------- sound/soc/tegra/tegra_wm8903.c | 22 ++++++------------- sound/soc/tegra/tegra_wm9712.c | 8 ++----- sound/soc/tegra/trimslice.c | 18 ++++------------ 11 files changed, 40 insertions(+), 130 deletions(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index ec39ecba1e8b..2839c6cb8c38 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -205,13 +205,11 @@ static int tegra_alc5632_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + goto err_put_cpu_of_node; } return 0; -err_fini_utils: - tegra_asoc_utils_fini(&alc5632->util_data); err_put_cpu_of_node: of_node_put(tegra_alc5632_dai.cpus->of_node); tegra_alc5632_dai.cpus->of_node = NULL; @@ -226,12 +224,9 @@ err: static int tegra_alc5632_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); - of_node_put(tegra_alc5632_dai.cpus->of_node); tegra_alc5632_dai.cpus->of_node = NULL; tegra_alc5632_dai.platforms->of_node = NULL; diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 536a578e9512..0d2271952555 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c @@ -175,52 +175,32 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, return -EINVAL; } - data->clk_pll_a = clk_get(dev, "pll_a"); + data->clk_pll_a = devm_clk_get(dev, "pll_a"); if (IS_ERR(data->clk_pll_a)) { dev_err(data->dev, "Can't retrieve clk pll_a\n"); - ret = PTR_ERR(data->clk_pll_a); - goto err; + return PTR_ERR(data->clk_pll_a); } - data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0"); + data->clk_pll_a_out0 = devm_clk_get(dev, "pll_a_out0"); if (IS_ERR(data->clk_pll_a_out0)) { dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); - ret = PTR_ERR(data->clk_pll_a_out0); - goto err_put_pll_a; + return PTR_ERR(data->clk_pll_a_out0); } - data->clk_cdev1 = clk_get(dev, "mclk"); + data->clk_cdev1 = devm_clk_get(dev, "mclk"); if (IS_ERR(data->clk_cdev1)) { dev_err(data->dev, "Can't retrieve clk cdev1\n"); - ret = PTR_ERR(data->clk_cdev1); - goto err_put_pll_a_out0; + return PTR_ERR(data->clk_cdev1); } ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100); if (ret) - goto err_put_cdev1; + return ret; return 0; - -err_put_cdev1: - clk_put(data->clk_cdev1); -err_put_pll_a_out0: - clk_put(data->clk_pll_a_out0); -err_put_pll_a: - clk_put(data->clk_pll_a); -err: - return ret; } EXPORT_SYMBOL_GPL(tegra_asoc_utils_init); -void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data) -{ - clk_put(data->clk_cdev1); - clk_put(data->clk_pll_a_out0); - clk_put(data->clk_pll_a); -} -EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini); - MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra ASoC utility code"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h index 0c13818dee75..a34439587d59 100644 --- a/sound/soc/tegra/tegra_asoc_utils.h +++ b/sound/soc/tegra/tegra_asoc_utils.h @@ -34,6 +34,5 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data); int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, struct device *dev); -void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data); #endif diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index d800b62b36f8..ec9050516cd7 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c @@ -218,19 +218,18 @@ static int tegra_max98090_probe(struct platform_device *pdev) ret = snd_soc_of_parse_card_name(card, "nvidia,model"); if (ret) - goto err; + return ret; ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); if (ret) - goto err; + return ret; tegra_max98090_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); if (!tegra_max98090_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } tegra_max98090_dai.cpus->of_node = of_parse_phandle(np, @@ -238,40 +237,31 @@ static int tegra_max98090_probe(struct platform_device *pdev) if (!tegra_max98090_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } 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; + return ret; ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + return ret; } return 0; - -err_fini_utils: - tegra_asoc_utils_fini(&machine->util_data); -err: - return ret; } static int tegra_max98090_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); - return 0; } diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 9878bc3eb89e..201d132731f9 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -164,19 +164,18 @@ static int tegra_rt5640_probe(struct platform_device *pdev) ret = snd_soc_of_parse_card_name(card, "nvidia,model"); if (ret) - goto err; + return ret; ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); if (ret) - goto err; + return ret; tegra_rt5640_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); if (!tegra_rt5640_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } tegra_rt5640_dai.cpus->of_node = of_parse_phandle(np, @@ -184,40 +183,31 @@ static int tegra_rt5640_probe(struct platform_device *pdev) if (!tegra_rt5640_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } 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; + return ret; ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + return ret; } return 0; - -err_fini_utils: - tegra_asoc_utils_fini(&machine->util_data); -err: - return ret; } static int tegra_rt5640_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); - return 0; } diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c index 5821313db977..8f71e21f6ee9 100644 --- a/sound/soc/tegra/tegra_rt5677.c +++ b/sound/soc/tegra/tegra_rt5677.c @@ -270,13 +270,11 @@ static int tegra_rt5677_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + goto err_put_cpu_of_node; } return 0; -err_fini_utils: - tegra_asoc_utils_fini(&machine->util_data); err_put_cpu_of_node: of_node_put(tegra_rt5677_dai.cpus->of_node); tegra_rt5677_dai.cpus->of_node = NULL; @@ -291,12 +289,9 @@ err: static int tegra_rt5677_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); - 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; diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c index dc411ba2e36d..692fcc3d7d6e 100644 --- a/sound/soc/tegra/tegra_sgtl5000.c +++ b/sound/soc/tegra/tegra_sgtl5000.c @@ -156,13 +156,11 @@ static int tegra_sgtl5000_driver_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + goto err_put_cpu_of_node; } return 0; -err_fini_utils: - tegra_asoc_utils_fini(&machine->util_data); err_put_cpu_of_node: of_node_put(tegra_sgtl5000_dai.cpus->of_node); tegra_sgtl5000_dai.cpus->of_node = NULL; @@ -177,13 +175,10 @@ err: static int tegra_sgtl5000_driver_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct tegra_sgtl5000 *machine = snd_soc_card_get_drvdata(card); int ret; ret = snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); - of_node_put(tegra_sgtl5000_dai.cpus->of_node); tegra_sgtl5000_dai.cpus->of_node = NULL; tegra_sgtl5000_dai.platforms->of_node = NULL; diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 0d653a605358..2ee2ed190872 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -127,19 +127,18 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev) ret = snd_soc_of_parse_card_name(card, "nvidia,model"); if (ret) - goto err; + return ret; ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); if (ret) - goto err; + return ret; tegra_wm8753_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); if (!tegra_wm8753_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } tegra_wm8753_dai.cpus->of_node = of_parse_phandle(np, @@ -147,40 +146,31 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev) if (!tegra_wm8753_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } 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; + return ret; ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + return ret; } return 0; - -err_fini_utils: - tegra_asoc_utils_fini(&machine->util_data); -err: - return ret; } static int tegra_wm8753_driver_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); - return 0; } diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 9b5651502f12..6525b93cb75c 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -319,19 +319,18 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev) ret = snd_soc_of_parse_card_name(card, "nvidia,model"); if (ret) - goto err; + return ret; ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); if (ret) - goto err; + return ret; tegra_wm8903_dai.codecs->of_node = of_parse_phandle(np, "nvidia,audio-codec", 0); if (!tegra_wm8903_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } tegra_wm8903_dai.cpus->of_node = of_parse_phandle(np, @@ -339,40 +338,31 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev) if (!tegra_wm8903_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } 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; + return ret; ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + return ret; } return 0; - -err_fini_utils: - tegra_asoc_utils_fini(&machine->util_data); -err: - return ret; } static int tegra_wm8903_driver_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); - return 0; } diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c index b85bd9f89073..726edfa21a29 100644 --- a/sound/soc/tegra/tegra_wm9712.c +++ b/sound/soc/tegra/tegra_wm9712.c @@ -113,19 +113,17 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev) ret = tegra_asoc_utils_set_ac97_rate(&machine->util_data); if (ret) - goto asoc_utils_fini; + goto codec_unregister; ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto asoc_utils_fini; + goto codec_unregister; } return 0; -asoc_utils_fini: - tegra_asoc_utils_fini(&machine->util_data); codec_unregister: platform_device_del(machine->codec); codec_put: @@ -140,8 +138,6 @@ static int tegra_wm9712_driver_remove(struct platform_device *pdev) snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); - platform_device_unregister(machine->codec); return 0; diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index f9834afaa2e8..6dca6836aa04 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -125,8 +125,7 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev) if (!trimslice_tlv320aic23_dai.codecs->of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } trimslice_tlv320aic23_dai.cpus->of_node = of_parse_phandle(np, @@ -134,8 +133,7 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev) if (!trimslice_tlv320aic23_dai.cpus->of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } trimslice_tlv320aic23_dai.platforms->of_node = @@ -143,32 +141,24 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev) ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); if (ret) - goto err; + return ret; ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + return ret; } return 0; - -err_fini_utils: - tegra_asoc_utils_fini(&trimslice->util_data); -err: - return ret; } static int tegra_snd_trimslice_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&trimslice->util_data); - return 0; } From facb0f4bb35c05fbda41bcd1ef1ddeb41ced4e9f Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 13 Jan 2020 23:24:22 -0800 Subject: [PATCH 077/428] ASoC: nau8825: Change Tegra clk_out_2 provider to PMC Tegra clk_out_1, clk_out_2, and clk_out_3 are part of PMC block and these clocks are moved from the clock driver to PMC driver with PMC as a provider for these clocks. Update bindings document to use PMC as clock provider for clk_out_2 and change ID to PMC clock ID. Reviewed-by: Dmitry Osipenko Acked-by: Rob Herring Signed-off-by: Sowjanya Komatineni Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/sound/nau8825.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/nau8825.txt b/Documentation/devicetree/bindings/sound/nau8825.txt index d16d96839bcb..388a7bc60b1f 100644 --- a/Documentation/devicetree/bindings/sound/nau8825.txt +++ b/Documentation/devicetree/bindings/sound/nau8825.txt @@ -101,5 +101,5 @@ Example: nuvoton,crosstalk-enable; clock-names = "mclk"; - clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>; + clocks = <&tegra_pmc TEGRA_PMC_CLK_OUT_2>; }; From 1e4e0bf136aa4b4aa59c1e6af19844bd6d807794 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 13 Jan 2020 23:24:23 -0800 Subject: [PATCH 078/428] ASoC: tegra: Add audio mclk parent configuration Tegra PMC clock clk_out_1 is dedicated for audio mclk from Tegra30 through Tegra210 and currently Tegra clock driver does the initial parent configuration for audio mclk and keeps it enabled by default. With the move of PMC clocks from clock driver into PMC driver, audio clocks parent configuration can be specified through the device tree using assigned-clock-parents property and audio mclk control should be taken care of by the audio driver. This patch has implementation for parent configuration when default parent configuration through assigned-clock-parents property is not specified in the device tree. Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Reviewed-by: Sameer Pujar Signed-off-by: Sowjanya Komatineni Signed-off-by: Thierry Reding --- sound/soc/tegra/tegra_asoc_utils.c | 68 ++++++++++++++++++------------ 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 0d2271952555..25903ed850c8 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c @@ -60,8 +60,6 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, data->set_mclk = 0; clk_disable_unprepare(data->clk_cdev1); - clk_disable_unprepare(data->clk_pll_a_out0); - clk_disable_unprepare(data->clk_pll_a); err = clk_set_rate(data->clk_pll_a, new_baseclock); if (err) { @@ -77,18 +75,6 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ - err = clk_prepare_enable(data->clk_pll_a); - if (err) { - dev_err(data->dev, "Can't enable pll_a: %d\n", err); - return err; - } - - err = clk_prepare_enable(data->clk_pll_a_out0); - if (err) { - dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); - return err; - } - err = clk_prepare_enable(data->clk_cdev1); if (err) { dev_err(data->dev, "Can't enable cdev1: %d\n", err); @@ -109,8 +95,6 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data) int err; clk_disable_unprepare(data->clk_cdev1); - clk_disable_unprepare(data->clk_pll_a_out0); - clk_disable_unprepare(data->clk_pll_a); /* * AC97 rate is fixed at 24.576MHz and is used for both the host @@ -130,18 +114,6 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data) /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ - err = clk_prepare_enable(data->clk_pll_a); - if (err) { - dev_err(data->dev, "Can't enable pll_a: %d\n", err); - return err; - } - - err = clk_prepare_enable(data->clk_pll_a_out0); - if (err) { - dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); - return err; - } - err = clk_prepare_enable(data->clk_cdev1); if (err) { dev_err(data->dev, "Can't enable cdev1: %d\n", err); @@ -158,6 +130,7 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_ac97_rate); int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, struct device *dev) { + struct clk *clk_out_1, *clk_extern1; int ret; data->dev = dev; @@ -193,6 +166,45 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, return PTR_ERR(data->clk_cdev1); } + /* + * If clock parents are not set in DT, configure here to use clk_out_1 + * as mclk and extern1 as parent for Tegra30 and higher. + */ + if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) && + data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA20) { + dev_warn(data->dev, + "Configuring clocks for a legacy device-tree\n"); + dev_warn(data->dev, + "Please update DT to use assigned-clock-parents\n"); + clk_extern1 = devm_clk_get(dev, "extern1"); + if (IS_ERR(clk_extern1)) { + dev_err(data->dev, "Can't retrieve clk extern1\n"); + return PTR_ERR(clk_extern1); + } + + ret = clk_set_parent(clk_extern1, data->clk_pll_a_out0); + if (ret < 0) { + dev_err(data->dev, + "Set parent failed for clk extern1\n"); + return ret; + } + + clk_out_1 = devm_clk_get(dev, "pmc_clk_out_1"); + if (IS_ERR(clk_out_1)) { + dev_err(data->dev, "Can't retrieve pmc_clk_out_1\n"); + return PTR_ERR(clk_out_1); + } + + ret = clk_set_parent(clk_out_1, clk_extern1); + if (ret < 0) { + dev_err(data->dev, + "Set parent failed for pmc_clk_out_1\n"); + return ret; + } + + data->clk_cdev1 = clk_out_1; + } + ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100); if (ret) return ret; From ff5d18cb04f4ecccbcf05b7f83ab6df2a0d95c16 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 13 Jan 2020 23:24:24 -0800 Subject: [PATCH 079/428] ASoC: tegra: Enable audio mclk during tegra_asoc_utils_init() Tegra PMC clock clk_out_1 is dedicated for audio mclk from Tegra30 through Tegra210 and currently Tegra clock driver keeps the audio mclk enabled. With the move of PMC clocks from clock driver into pmc driver, audio mclk enable from clock driver is removed and this should be taken care of by the audio driver. tegra_asoc_utils_init() calls tegra_asoc_utils_set_rate() and audio mclk rate configuration is not needed during init and the rate is actually set during the ->hw_params() callback. So, this patch removes tegra_asoc_utils_set_rate() call and just leaves the audio mclk enabled. Signed-off-by: Sowjanya Komatineni Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- sound/soc/tegra/tegra_asoc_utils.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 25903ed850c8..587f62a288d1 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c @@ -205,9 +205,16 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, data->clk_cdev1 = clk_out_1; } - ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100); - if (ret) + /* + * FIXME: There is some unknown dependency between audio mclk disable + * and suspend-resume functionality on Tegra30, although audio mclk is + * only needed for audio. + */ + ret = clk_prepare_enable(data->clk_cdev1); + if (ret) { + dev_err(data->dev, "Can't enable cdev1: %d\n", ret); return ret; + } return 0; } From 7470704d8b425c4c7045884690f92cf015563aac Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 16 Apr 2020 20:25:31 +0800 Subject: [PATCH 080/428] ASoC: fsl_asrc: rename asrc_priv to asrc In order to move common structure to fsl_asrc_common.h we change the name of asrc_priv to asrc, the asrc_priv will be used by new struct fsl_asrc_priv. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/722142c2e1b57a95f911db1d42d901b88fc283d6.1587038908.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 298 +++++++++++++++++------------------ sound/soc/fsl/fsl_asrc.h | 4 +- sound/soc/fsl/fsl_asrc_dma.c | 24 +-- 3 files changed, 163 insertions(+), 163 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 0dcebc24c312..4d3e51bfa949 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -21,10 +21,10 @@ #define IDEAL_RATIO_DECIMAL_DEPTH 26 #define pair_err(fmt, ...) \ - dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) + dev_err(&asrc->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) #define pair_dbg(fmt, ...) \ - dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) + dev_dbg(&asrc->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) /* Corresponding to process_option */ static unsigned int supported_asrc_rate[] = { @@ -157,15 +157,15 @@ static void fsl_asrc_sel_proc(int inrate, int outrate, int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) { enum asrc_pair_index index = ASRC_INVALID_PAIR; - struct fsl_asrc *asrc_priv = pair->asrc_priv; - struct device *dev = &asrc_priv->pdev->dev; + struct fsl_asrc *asrc = pair->asrc; + struct device *dev = &asrc->pdev->dev; unsigned long lock_flags; int i, ret = 0; - spin_lock_irqsave(&asrc_priv->lock, lock_flags); + spin_lock_irqsave(&asrc->lock, lock_flags); for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) { - if (asrc_priv->pair[i] != NULL) + if (asrc->pair[i] != NULL) continue; index = i; @@ -177,17 +177,17 @@ int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) if (index == ASRC_INVALID_PAIR) { dev_err(dev, "all pairs are busy now\n"); ret = -EBUSY; - } else if (asrc_priv->channel_avail < channels) { + } else if (asrc->channel_avail < channels) { dev_err(dev, "can't afford required channels: %d\n", channels); ret = -EINVAL; } else { - asrc_priv->channel_avail -= channels; - asrc_priv->pair[index] = pair; + asrc->channel_avail -= channels; + asrc->pair[index] = pair; pair->channels = channels; pair->index = index; } - spin_unlock_irqrestore(&asrc_priv->lock, lock_flags); + spin_unlock_irqrestore(&asrc->lock, lock_flags); return ret; } @@ -195,25 +195,25 @@ int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) /** * Release ASRC pair * - * It clears the resource from asrc_priv and releases the occupied channels. + * It clears the resource from asrc and releases the occupied channels. */ void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) { - struct fsl_asrc *asrc_priv = pair->asrc_priv; + struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; unsigned long lock_flags; /* Make sure the pair is disabled */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEi_MASK(index), 0); - spin_lock_irqsave(&asrc_priv->lock, lock_flags); + spin_lock_irqsave(&asrc->lock, lock_flags); - asrc_priv->channel_avail += pair->channels; - asrc_priv->pair[index] = NULL; + asrc->channel_avail += pair->channels; + asrc->pair[index] = NULL; pair->error = 0; - spin_unlock_irqrestore(&asrc_priv->lock, lock_flags); + spin_unlock_irqrestore(&asrc->lock, lock_flags); } /** @@ -221,10 +221,10 @@ void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) */ static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out) { - struct fsl_asrc *asrc_priv = pair->asrc_priv; + struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; - regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), + regmap_update_bits(asrc->regmap, REG_ASRMCR(index), ASRMCRi_EXTTHRSHi_MASK | ASRMCRi_INFIFO_THRESHOLD_MASK | ASRMCRi_OUTFIFO_THRESHOLD_MASK, @@ -257,7 +257,7 @@ static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div) static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, int inrate, int outrate) { - struct fsl_asrc *asrc_priv = pair->asrc_priv; + struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; unsigned long ratio; int i; @@ -286,8 +286,8 @@ static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, break; } - regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio); - regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24); + regmap_write(asrc->regmap, REG_ASRIDRL(index), ratio); + regmap_write(asrc->regmap, REG_ASRIDRH(index), ratio >> 24); return 0; } @@ -309,7 +309,7 @@ static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) { struct asrc_config *config = pair->config; - struct fsl_asrc *asrc_priv = pair->asrc_priv; + struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; enum asrc_word_width input_word_width; enum asrc_word_width output_word_width; @@ -392,11 +392,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) } /* Validate input and output clock sources */ - clk_index[IN] = asrc_priv->clk_map[IN][config->inclk]; - clk_index[OUT] = asrc_priv->clk_map[OUT][config->outclk]; + clk_index[IN] = asrc->clk_map[IN][config->inclk]; + clk_index[OUT] = asrc->clk_map[OUT][config->outclk]; /* We only have output clock for ideal ratio mode */ - clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]]; + clk = asrc->asrck_clk[clk_index[ideal ? OUT : IN]]; clk_rate = clk_get_rate(clk); rem[IN] = do_div(clk_rate, inrate); @@ -417,7 +417,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) div[IN] = min_t(u32, 1024, div[IN]); - clk = asrc_priv->asrck_clk[clk_index[OUT]]; + clk = asrc->asrck_clk[clk_index[OUT]]; clk_rate = clk_get_rate(clk); if (ideal && use_ideal_rate) rem[OUT] = do_div(clk_rate, IDEAL_RATIO_RATE); @@ -437,22 +437,22 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) /* Set the channel number */ channels = config->channel_num; - if (asrc_priv->soc->channel_bits < 4) + if (asrc->soc->channel_bits < 4) channels /= 2; /* Update channels for current pair */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR, - ASRCNCR_ANCi_MASK(index, asrc_priv->soc->channel_bits), - ASRCNCR_ANCi(index, channels, asrc_priv->soc->channel_bits)); + regmap_update_bits(asrc->regmap, REG_ASRCNCR, + ASRCNCR_ANCi_MASK(index, asrc->soc->channel_bits), + ASRCNCR_ANCi(index, channels, asrc->soc->channel_bits)); /* Default setting: Automatic selection for processing mode */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index)); - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_USRi_MASK(index), 0); /* Set the input and output clock sources */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCSR, + regmap_update_bits(asrc->regmap, REG_ASRCSR, ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index), ASRCSR_AICS(index, clk_index[IN]) | ASRCSR_AOCS(index, clk_index[OUT])); @@ -462,19 +462,19 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]); /* Suppose indiv and outdiv includes prescaler, so add its MASK too */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index), + regmap_update_bits(asrc->regmap, REG_ASRCDR(index), ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) | ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index), ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv)); /* Implement word_width configurations */ - regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index), + regmap_update_bits(asrc->regmap, REG_ASRMCR1(index), ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK, ASRMCR1i_OW16(output_word_width) | ASRMCR1i_IWD(input_word_width)); /* Enable BUFFER STALL */ - regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), + regmap_update_bits(asrc->regmap, REG_ASRMCR(index), ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi); /* Set default thresholds for input and output FIFO */ @@ -486,18 +486,18 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) return 0; /* Clear ASTSx bit to use Ideal Ratio mode */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ATSi_MASK(index), 0); /* Enable Ideal Ratio mode */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_update_bits(asrc->regmap, REG_ASRCTR, 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, + regmap_update_bits(asrc->regmap, REG_ASRCFG, ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index), ASRCFG_PREMOD(index, pre_proc) | ASRCFG_POSTMOD(index, post_proc)); @@ -512,28 +512,28 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) */ static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair) { - struct fsl_asrc *asrc_priv = pair->asrc_priv; + struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; int reg, retry = 10, i; /* Enable the current pair */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEi_MASK(index), ASRCTR_ASRCE(index)); /* Wait for status of initialization */ do { udelay(5); - regmap_read(asrc_priv->regmap, REG_ASRCFG, ®); + regmap_read(asrc->regmap, REG_ASRCFG, ®); reg &= ASRCFG_INIRQi_MASK(index); } while (!reg && --retry); /* Make the input fifo to ASRC STALL level */ - regmap_read(asrc_priv->regmap, REG_ASRCNCR, ®); + regmap_read(asrc->regmap, REG_ASRCNCR, ®); for (i = 0; i < pair->channels * 4; i++) - regmap_write(asrc_priv->regmap, REG_ASRDI(index), 0); + regmap_write(asrc->regmap, REG_ASRDI(index), 0); /* Enable overload interrupt */ - regmap_write(asrc_priv->regmap, REG_ASRIER, ASRIER_AOLIE); + regmap_write(asrc->regmap, REG_ASRIER, ASRIER_AOLIE); } /** @@ -541,11 +541,11 @@ static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair) */ static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) { - struct fsl_asrc *asrc_priv = pair->asrc_priv; + struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; /* Stop the current pair */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEi_MASK(index), 0); } @@ -554,23 +554,23 @@ static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) */ struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) { - struct fsl_asrc *asrc_priv = pair->asrc_priv; + struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; char name[4]; sprintf(name, "%cx%c", dir == IN ? 'r' : 't', index + 'a'); - return dma_request_slave_channel(&asrc_priv->pdev->dev, name); + return dma_request_slave_channel(&asrc->pdev->dev, name); } EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel); static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); + struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai); /* Odd channel number is not valid for older ASRC (channel_bits==3) */ - if (asrc_priv->soc->channel_bits == 3) + if (asrc->soc->channel_bits == 3) snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); @@ -583,7 +583,7 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); + struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai); struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; unsigned int channels = params_channels(params); @@ -600,7 +600,7 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, pair->config = &config; - if (asrc_priv->asrc_width == 16) + if (asrc->asrc_width == 16) format = SNDRV_PCM_FORMAT_S16_LE; else format = SNDRV_PCM_FORMAT_S24_LE; @@ -614,11 +614,11 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, config.input_format = params_format(params); config.output_format = format; config.input_sample_rate = rate; - config.output_sample_rate = asrc_priv->asrc_rate; + config.output_sample_rate = asrc->asrc_rate; } else { config.input_format = format; config.output_format = params_format(params); - config.input_sample_rate = asrc_priv->asrc_rate; + config.input_sample_rate = asrc->asrc_rate; config.output_sample_rate = rate; } @@ -676,10 +676,10 @@ static const struct snd_soc_dai_ops fsl_asrc_dai_ops = { static int fsl_asrc_dai_probe(struct snd_soc_dai *dai) { - struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); + struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai); - snd_soc_dai_init_dma_data(dai, &asrc_priv->dma_params_tx, - &asrc_priv->dma_params_rx); + snd_soc_dai_init_dma_data(dai, &asrc->dma_params_tx, + &asrc->dma_params_rx); return 0; } @@ -858,30 +858,30 @@ static const struct regmap_config fsl_asrc_regmap_config = { /** * Initialize ASRC registers with a default configurations */ -static int fsl_asrc_init(struct fsl_asrc *asrc_priv) +static int fsl_asrc_init(struct fsl_asrc *asrc) { /* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */ - regmap_write(asrc_priv->regmap, REG_ASRCTR, ASRCTR_ASRCEN); + regmap_write(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEN); /* Disable interrupt by default */ - regmap_write(asrc_priv->regmap, REG_ASRIER, 0x0); + regmap_write(asrc->regmap, REG_ASRIER, 0x0); /* Apply recommended settings for parameters from Reference Manual */ - regmap_write(asrc_priv->regmap, REG_ASRPM1, 0x7fffff); - regmap_write(asrc_priv->regmap, REG_ASRPM2, 0x255555); - regmap_write(asrc_priv->regmap, REG_ASRPM3, 0xff7280); - regmap_write(asrc_priv->regmap, REG_ASRPM4, 0xff7280); - regmap_write(asrc_priv->regmap, REG_ASRPM5, 0xff7280); + regmap_write(asrc->regmap, REG_ASRPM1, 0x7fffff); + regmap_write(asrc->regmap, REG_ASRPM2, 0x255555); + regmap_write(asrc->regmap, REG_ASRPM3, 0xff7280); + regmap_write(asrc->regmap, REG_ASRPM4, 0xff7280); + regmap_write(asrc->regmap, REG_ASRPM5, 0xff7280); /* Base address for task queue FIFO. Set to 0x7C */ - regmap_update_bits(asrc_priv->regmap, REG_ASRTFR1, + regmap_update_bits(asrc->regmap, REG_ASRTFR1, ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc)); /* Set the processing clock for 76KHz to 133M */ - regmap_write(asrc_priv->regmap, REG_ASR76K, 0x06D6); + regmap_write(asrc->regmap, REG_ASR76K, 0x06D6); /* Set the processing clock for 56KHz to 133M */ - return regmap_write(asrc_priv->regmap, REG_ASR56K, 0x0947); + return regmap_write(asrc->regmap, REG_ASR56K, 0x0947); } /** @@ -889,15 +889,15 @@ static int fsl_asrc_init(struct fsl_asrc *asrc_priv) */ static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) { - struct fsl_asrc *asrc_priv = (struct fsl_asrc *)dev_id; - struct device *dev = &asrc_priv->pdev->dev; + struct fsl_asrc *asrc = (struct fsl_asrc *)dev_id; + struct device *dev = &asrc->pdev->dev; enum asrc_pair_index index; u32 status; - regmap_read(asrc_priv->regmap, REG_ASRSTR, &status); + regmap_read(asrc->regmap, REG_ASRSTR, &status); /* Clean overload error */ - regmap_write(asrc_priv->regmap, REG_ASRSTR, ASRSTR_AOLE); + regmap_write(asrc->regmap, REG_ASRSTR, ASRSTR_AOLE); /* * We here use dev_dbg() for all exceptions because ASRC itself does @@ -905,31 +905,31 @@ static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) * interrupt would result a ridged conversion. */ for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) { - if (!asrc_priv->pair[index]) + if (!asrc->pair[index]) continue; if (status & ASRSTR_ATQOL) { - asrc_priv->pair[index]->error |= ASRC_TASK_Q_OVERLOAD; + asrc->pair[index]->error |= ASRC_TASK_Q_OVERLOAD; dev_dbg(dev, "ASRC Task Queue FIFO overload\n"); } if (status & ASRSTR_AOOL(index)) { - asrc_priv->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD; + asrc->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD; pair_dbg("Output Task Overload\n"); } if (status & ASRSTR_AIOL(index)) { - asrc_priv->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD; + asrc->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD; pair_dbg("Input Task Overload\n"); } if (status & ASRSTR_AODO(index)) { - asrc_priv->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW; + asrc->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW; pair_dbg("Output Data Buffer has overflowed\n"); } if (status & ASRSTR_AIDU(index)) { - asrc_priv->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN; + asrc->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN; pair_dbg("Input Data Buffer has underflowed\n"); } } @@ -940,18 +940,18 @@ static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) static int fsl_asrc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct fsl_asrc *asrc_priv; + struct fsl_asrc *asrc; struct resource *res; void __iomem *regs; int irq, ret, i; u32 map_idx; char tmp[16]; - asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL); - if (!asrc_priv) + asrc = devm_kzalloc(&pdev->dev, sizeof(*asrc), GFP_KERNEL); + if (!asrc) return -ENOMEM; - asrc_priv->pdev = pdev; + asrc->pdev = pdev; /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -959,13 +959,13 @@ static int fsl_asrc_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - asrc_priv->paddr = res->start; + asrc->paddr = res->start; - asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs, - &fsl_asrc_regmap_config); - if (IS_ERR(asrc_priv->regmap)) { + asrc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs, + &fsl_asrc_regmap_config); + if (IS_ERR(asrc->regmap)) { dev_err(&pdev->dev, "failed to init regmap\n"); - return PTR_ERR(asrc_priv->regmap); + return PTR_ERR(asrc->regmap); } irq = platform_get_irq(pdev, 0); @@ -973,49 +973,49 @@ static int fsl_asrc_probe(struct platform_device *pdev) return irq; ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, - dev_name(&pdev->dev), asrc_priv); + dev_name(&pdev->dev), asrc); if (ret) { dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret); return ret; } - asrc_priv->mem_clk = devm_clk_get(&pdev->dev, "mem"); - if (IS_ERR(asrc_priv->mem_clk)) { + asrc->mem_clk = devm_clk_get(&pdev->dev, "mem"); + if (IS_ERR(asrc->mem_clk)) { dev_err(&pdev->dev, "failed to get mem clock\n"); - return PTR_ERR(asrc_priv->mem_clk); + return PTR_ERR(asrc->mem_clk); } - asrc_priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); - if (IS_ERR(asrc_priv->ipg_clk)) { + asrc->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(asrc->ipg_clk)) { dev_err(&pdev->dev, "failed to get ipg clock\n"); - return PTR_ERR(asrc_priv->ipg_clk); + return PTR_ERR(asrc->ipg_clk); } - asrc_priv->spba_clk = devm_clk_get(&pdev->dev, "spba"); - if (IS_ERR(asrc_priv->spba_clk)) + asrc->spba_clk = devm_clk_get(&pdev->dev, "spba"); + if (IS_ERR(asrc->spba_clk)) dev_warn(&pdev->dev, "failed to get spba clock\n"); for (i = 0; i < ASRC_CLK_MAX_NUM; i++) { sprintf(tmp, "asrck_%x", i); - asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp); - if (IS_ERR(asrc_priv->asrck_clk[i])) { + asrc->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp); + if (IS_ERR(asrc->asrck_clk[i])) { dev_err(&pdev->dev, "failed to get %s clock\n", tmp); - return PTR_ERR(asrc_priv->asrck_clk[i]); + return PTR_ERR(asrc->asrck_clk[i]); } } - asrc_priv->soc = of_device_get_match_data(&pdev->dev); - if (!asrc_priv->soc) { + asrc->soc = of_device_get_match_data(&pdev->dev); + if (!asrc->soc) { dev_err(&pdev->dev, "failed to get soc data\n"); return -ENODEV; } if (of_device_is_compatible(np, "fsl,imx35-asrc")) { - asrc_priv->clk_map[IN] = input_clk_map_imx35; - asrc_priv->clk_map[OUT] = output_clk_map_imx35; + asrc->clk_map[IN] = input_clk_map_imx35; + asrc->clk_map[OUT] = output_clk_map_imx35; } else if (of_device_is_compatible(np, "fsl,imx53-asrc")) { - asrc_priv->clk_map[IN] = input_clk_map_imx53; - asrc_priv->clk_map[OUT] = output_clk_map_imx53; + asrc->clk_map[IN] = input_clk_map_imx53; + asrc->clk_map[OUT] = output_clk_map_imx53; } else if (of_device_is_compatible(np, "fsl,imx8qm-asrc") || of_device_is_compatible(np, "fsl,imx8qxp-asrc")) { ret = of_property_read_u32(np, "fsl,asrc-clk-map", &map_idx); @@ -1029,44 +1029,44 @@ static int fsl_asrc_probe(struct platform_device *pdev) return -EINVAL; } if (of_device_is_compatible(np, "fsl,imx8qm-asrc")) { - asrc_priv->clk_map[IN] = clk_map_imx8qm[map_idx]; - asrc_priv->clk_map[OUT] = clk_map_imx8qm[map_idx]; + asrc->clk_map[IN] = clk_map_imx8qm[map_idx]; + asrc->clk_map[OUT] = clk_map_imx8qm[map_idx]; } else { - asrc_priv->clk_map[IN] = clk_map_imx8qxp[map_idx]; - asrc_priv->clk_map[OUT] = clk_map_imx8qxp[map_idx]; + asrc->clk_map[IN] = clk_map_imx8qxp[map_idx]; + asrc->clk_map[OUT] = clk_map_imx8qxp[map_idx]; } } - ret = fsl_asrc_init(asrc_priv); + ret = fsl_asrc_init(asrc); if (ret) { dev_err(&pdev->dev, "failed to init asrc %d\n", ret); return ret; } - asrc_priv->channel_avail = 10; + asrc->channel_avail = 10; ret = of_property_read_u32(np, "fsl,asrc-rate", - &asrc_priv->asrc_rate); + &asrc->asrc_rate); if (ret) { dev_err(&pdev->dev, "failed to get output rate\n"); return ret; } ret = of_property_read_u32(np, "fsl,asrc-width", - &asrc_priv->asrc_width); + &asrc->asrc_width); if (ret) { dev_err(&pdev->dev, "failed to get output width\n"); return ret; } - if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) { + if (asrc->asrc_width != 16 && asrc->asrc_width != 24) { dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n"); - asrc_priv->asrc_width = 24; + asrc->asrc_width = 24; } - platform_set_drvdata(pdev, asrc_priv); + platform_set_drvdata(pdev, asrc); pm_runtime_enable(&pdev->dev); - spin_lock_init(&asrc_priv->lock); + spin_lock_init(&asrc->lock); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component, &fsl_asrc_dai, 1); @@ -1081,22 +1081,22 @@ static int fsl_asrc_probe(struct platform_device *pdev) #ifdef CONFIG_PM static int fsl_asrc_runtime_resume(struct device *dev) { - struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); + struct fsl_asrc *asrc = dev_get_drvdata(dev); int i, ret; - ret = clk_prepare_enable(asrc_priv->mem_clk); + ret = clk_prepare_enable(asrc->mem_clk); if (ret) return ret; - ret = clk_prepare_enable(asrc_priv->ipg_clk); + ret = clk_prepare_enable(asrc->ipg_clk); if (ret) goto disable_mem_clk; - if (!IS_ERR(asrc_priv->spba_clk)) { - ret = clk_prepare_enable(asrc_priv->spba_clk); + if (!IS_ERR(asrc->spba_clk)) { + ret = clk_prepare_enable(asrc->spba_clk); if (ret) goto disable_ipg_clk; } for (i = 0; i < ASRC_CLK_MAX_NUM; i++) { - ret = clk_prepare_enable(asrc_priv->asrck_clk[i]); + ret = clk_prepare_enable(asrc->asrck_clk[i]); if (ret) goto disable_asrck_clk; } @@ -1105,27 +1105,27 @@ static int fsl_asrc_runtime_resume(struct device *dev) disable_asrck_clk: for (i--; i >= 0; i--) - clk_disable_unprepare(asrc_priv->asrck_clk[i]); - if (!IS_ERR(asrc_priv->spba_clk)) - clk_disable_unprepare(asrc_priv->spba_clk); + clk_disable_unprepare(asrc->asrck_clk[i]); + if (!IS_ERR(asrc->spba_clk)) + clk_disable_unprepare(asrc->spba_clk); disable_ipg_clk: - clk_disable_unprepare(asrc_priv->ipg_clk); + clk_disable_unprepare(asrc->ipg_clk); disable_mem_clk: - clk_disable_unprepare(asrc_priv->mem_clk); + clk_disable_unprepare(asrc->mem_clk); return ret; } static int fsl_asrc_runtime_suspend(struct device *dev) { - struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); + struct fsl_asrc *asrc = dev_get_drvdata(dev); int i; for (i = 0; i < ASRC_CLK_MAX_NUM; i++) - clk_disable_unprepare(asrc_priv->asrck_clk[i]); - if (!IS_ERR(asrc_priv->spba_clk)) - clk_disable_unprepare(asrc_priv->spba_clk); - clk_disable_unprepare(asrc_priv->ipg_clk); - clk_disable_unprepare(asrc_priv->mem_clk); + clk_disable_unprepare(asrc->asrck_clk[i]); + if (!IS_ERR(asrc->spba_clk)) + clk_disable_unprepare(asrc->spba_clk); + clk_disable_unprepare(asrc->ipg_clk); + clk_disable_unprepare(asrc->mem_clk); return 0; } @@ -1134,37 +1134,37 @@ static int fsl_asrc_runtime_suspend(struct device *dev) #ifdef CONFIG_PM_SLEEP static int fsl_asrc_suspend(struct device *dev) { - struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); + struct fsl_asrc *asrc = dev_get_drvdata(dev); - regmap_read(asrc_priv->regmap, REG_ASRCFG, - &asrc_priv->regcache_cfg); + regmap_read(asrc->regmap, REG_ASRCFG, + &asrc->regcache_cfg); - regcache_cache_only(asrc_priv->regmap, true); - regcache_mark_dirty(asrc_priv->regmap); + regcache_cache_only(asrc->regmap, true); + regcache_mark_dirty(asrc->regmap); return 0; } static int fsl_asrc_resume(struct device *dev) { - struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); + struct fsl_asrc *asrc = dev_get_drvdata(dev); u32 asrctr; /* Stop all pairs provisionally */ - regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr); - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_read(asrc->regmap, REG_ASRCTR, &asrctr); + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEi_ALL_MASK, 0); /* Restore all registers */ - regcache_cache_only(asrc_priv->regmap, false); - regcache_sync(asrc_priv->regmap); + regcache_cache_only(asrc->regmap, false); + regcache_sync(asrc->regmap); - regmap_update_bits(asrc_priv->regmap, REG_ASRCFG, + regmap_update_bits(asrc->regmap, REG_ASRCFG, ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK | - ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg); + ASRCFG_PREMODi_ALL_MASK, asrc->regcache_cfg); /* Restart enabled pairs */ - regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEi_ALL_MASK, asrctr); return 0; diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h index 8a821132d9d0..95d62c45afde 100644 --- a/sound/soc/fsl/fsl_asrc.h +++ b/sound/soc/fsl/fsl_asrc.h @@ -448,7 +448,7 @@ struct fsl_asrc_soc_data { /** * fsl_asrc_pair: ASRC Pair private data * - * @asrc_priv: pointer to its parent module + * @asrc: pointer to its parent module * @config: configuration profile * @error: error record * @index: pair index (ASRC_PAIR_A, ASRC_PAIR_B, ASRC_PAIR_C) @@ -460,7 +460,7 @@ struct fsl_asrc_soc_data { * @private: pair private area */ struct fsl_asrc_pair { - struct fsl_asrc *asrc_priv; + struct fsl_asrc *asrc; struct asrc_config *config; unsigned int error; diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index e7178817d7a7..5fe83aece25b 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -135,7 +135,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, struct snd_dmaengine_dai_dma_data *dma_params_be = NULL; struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; - struct fsl_asrc *asrc_priv = pair->asrc_priv; + struct fsl_asrc *asrc = pair->asrc; struct dma_slave_config config_fe, config_be; enum asrc_pair_index index = pair->index; struct device *dev = component->dev; @@ -170,7 +170,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, /* Override dma_data of the Front-End and config its dmaengine */ dma_params_fe = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); - dma_params_fe->addr = asrc_priv->paddr + REG_ASRDx(!dir, index); + dma_params_fe->addr = asrc->paddr + REG_ASRDx(!dir, index); dma_params_fe->maxburst = dma_params_be->maxburst; pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir); @@ -203,7 +203,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, * need to configure dma_request and dma_request2, but get dma_chan via * dma_request_slave_channel directly with dma name of Front-End device */ - if (!asrc_priv->soc->use_edma) { + if (!asrc->soc->use_edma) { /* Get DMA request of Back-End */ tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx"); tmp_data = tmp_chan->private; @@ -230,7 +230,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, return -EINVAL; } - if (asrc_priv->asrc_width == 16) + if (asrc->asrc_width == 16) buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; else buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -242,10 +242,10 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, config_be.dst_maxburst = dma_params_be->maxburst; if (tx) { - config_be.src_addr = asrc_priv->paddr + REG_ASRDO(index); + config_be.src_addr = asrc->paddr + REG_ASRDO(index); config_be.dst_addr = dma_params_be->addr; } else { - config_be.dst_addr = asrc_priv->paddr + REG_ASRDI(index); + config_be.dst_addr = asrc->paddr + REG_ASRDI(index); config_be.src_addr = dma_params_be->addr; } @@ -288,7 +288,7 @@ static int fsl_asrc_dma_startup(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dmaengine_dai_dma_data *dma_data; struct device *dev = component->dev; - struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); + struct fsl_asrc *asrc = dev_get_drvdata(dev); struct fsl_asrc_pair *pair; struct dma_chan *tmp_chan = NULL; u8 dir = tx ? OUT : IN; @@ -306,7 +306,7 @@ static int fsl_asrc_dma_startup(struct snd_soc_component *component, if (!pair) return -ENOMEM; - pair->asrc_priv = asrc_priv; + pair->asrc = asrc; runtime->private_data = pair; @@ -361,15 +361,15 @@ static int fsl_asrc_dma_shutdown(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; - struct fsl_asrc *asrc_priv; + struct fsl_asrc *asrc; if (!pair) return 0; - asrc_priv = pair->asrc_priv; + asrc = pair->asrc; - if (asrc_priv->pair[pair->index] == pair) - asrc_priv->pair[pair->index] = NULL; + if (asrc->pair[pair->index] == pair) + asrc->pair[pair->index] = NULL; kfree(pair); From b84b4c9a688d803b0e7cf91fec9a5d8b3ba47768 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 16 Apr 2020 20:25:32 +0800 Subject: [PATCH 081/428] ASoC: dt-bindings: fsl_asrc: Add new property fsl, asrc-format In order to support new EASRC and simplify the code structure, We decide to share the common structure between them. This bring a problem that EASRC accept format directly from devicetree, but ASRC accept width from devicetree. In order to align with new ESARC, we add new property fsl,asrc-format. The fsl,asrc-format can replace the fsl,asrc-width, then driver can accept format from devicetree, don't need to convert it to format through width. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Acked-by: Rob Herring Link: https://lore.kernel.org/r/e7acbde4b26a82b674a4091515a219e09f847eac.1587038908.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,asrc.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/fsl,asrc.txt b/Documentation/devicetree/bindings/sound/fsl,asrc.txt index cb9a25165503..998b4c8a7f78 100644 --- a/Documentation/devicetree/bindings/sound/fsl,asrc.txt +++ b/Documentation/devicetree/bindings/sound/fsl,asrc.txt @@ -51,6 +51,10 @@ Optional properties: will be in use as default. Otherwise, the big endian mode will be in use for all the device registers. + - fsl,asrc-format : Defines a mutual sample format used by DPCM Back + Ends, which can replace the fsl,asrc-width. + The value is 2 (S16_LE), or 6 (S24_LE). + Example: asrc: asrc@2034000 { From 859e364302c510cfdd9abda13a3c4c1d1bc68c57 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 16 Apr 2020 20:25:33 +0800 Subject: [PATCH 082/428] ASoC: fsl-asoc-card: Support new property fsl, asrc-format In order to align with new ESARC, we add new property fsl,asrc-format. The fsl,asrc-format can replace the fsl,asrc-width, driver can accept format from devicetree, don't need to convert it to format through width. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/02f53d5512b9acd3492e2acdd5e0ba3113f18009.1587038908.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index bb33601fab84..cf4feb835743 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -680,17 +680,23 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto asrc_fail; } - ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width); + ret = of_property_read_u32(asrc_np, "fsl,asrc-format", + &priv->asrc_format); if (ret) { - dev_err(&pdev->dev, "failed to get output rate\n"); - ret = -EINVAL; - goto asrc_fail; - } + /* Fallback to old binding; translate to asrc_format */ + ret = of_property_read_u32(asrc_np, "fsl,asrc-width", + &width); + if (ret) { + dev_err(&pdev->dev, + "failed to decide output format\n"); + goto asrc_fail; + } - if (width == 24) - priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE; - else - priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE; + if (width == 24) + priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE; + else + priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE; + } } /* Finish card registering */ From 4520af41fd21863d026d53c7e1eb987509cb3c24 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 16 Apr 2020 20:25:34 +0800 Subject: [PATCH 083/428] ASoC: fsl_asrc: Support new property fsl,asrc-format In order to align with new ESARC, we add new property fsl,asrc-format. The fsl,asrc-format can replace the fsl,asrc-width, driver can accept format from devicetree, don't need to convert it to format through width. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/2be9664768f32982ba4f71e49749f7390096ac9f.1587038908.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 41 +++++++++++++++++++++++------------- sound/soc/fsl/fsl_asrc.h | 4 ++-- sound/soc/fsl/fsl_asrc_dma.c | 15 ++++++++++--- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 4d3e51bfa949..a9458fe268bc 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -589,7 +589,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); struct asrc_config config; - snd_pcm_format_t format; int ret; ret = fsl_asrc_request_pair(channels, pair); @@ -600,11 +599,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, pair->config = &config; - if (asrc->asrc_width == 16) - format = SNDRV_PCM_FORMAT_S16_LE; - else - format = SNDRV_PCM_FORMAT_S24_LE; - config.pair = pair->index; config.channel_num = channels; config.inclk = INCLK_NONE; @@ -612,11 +606,11 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { config.input_format = params_format(params); - config.output_format = format; + config.output_format = asrc->asrc_format; config.input_sample_rate = rate; config.output_sample_rate = asrc->asrc_rate; } else { - config.input_format = format; + config.input_format = asrc->asrc_format; config.output_format = params_format(params); config.input_sample_rate = asrc->asrc_rate; config.output_sample_rate = rate; @@ -946,6 +940,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) int irq, ret, i; u32 map_idx; char tmp[16]; + u32 width; asrc = devm_kzalloc(&pdev->dev, sizeof(*asrc), GFP_KERNEL); if (!asrc) @@ -1052,16 +1047,32 @@ static int fsl_asrc_probe(struct platform_device *pdev) return ret; } - ret = of_property_read_u32(np, "fsl,asrc-width", - &asrc->asrc_width); + ret = of_property_read_u32(np, "fsl,asrc-format", &asrc->asrc_format); if (ret) { - dev_err(&pdev->dev, "failed to get output width\n"); - return ret; + ret = of_property_read_u32(np, "fsl,asrc-width", &width); + if (ret) { + dev_err(&pdev->dev, "failed to decide output format\n"); + return ret; + } + + switch (width) { + case 16: + asrc->asrc_format = SNDRV_PCM_FORMAT_S16_LE; + break; + case 24: + asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE; + break; + default: + dev_warn(&pdev->dev, + "unsupported width, use default S24_LE\n"); + asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE; + break; + } } - if (asrc->asrc_width != 16 && asrc->asrc_width != 24) { - dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n"); - asrc->asrc_width = 24; + if (!(FSL_ASRC_FORMATS & (1ULL << asrc->asrc_format))) { + dev_warn(&pdev->dev, "unsupported width, use default S24_LE\n"); + asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE; } platform_set_drvdata(pdev, asrc); diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h index 95d62c45afde..3b0f156af2c3 100644 --- a/sound/soc/fsl/fsl_asrc.h +++ b/sound/soc/fsl/fsl_asrc.h @@ -493,7 +493,7 @@ struct fsl_asrc_pair { * @channel_avail: non-occupied channel numbers * @clk_map: clock map for input/output clock * @asrc_rate: default sample rate for ASoC Back-Ends - * @asrc_width: default sample width for ASoC Back-Ends + * @asrc_format: default sample format for ASoC Back-Ends * @regcache_cfg: store register value of REG_ASRCFG */ struct fsl_asrc { @@ -514,7 +514,7 @@ struct fsl_asrc { unsigned char *clk_map[2]; int asrc_rate; - int asrc_width; + snd_pcm_format_t asrc_format; u32 regcache_cfg; }; diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index 5fe83aece25b..a9dd3155ff35 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -146,7 +146,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, struct device *dev_be; u8 dir = tx ? OUT : IN; dma_cap_mask_t mask; - int ret; + int ret, width; /* Fetch the Back-End dma_data from DPCM */ for_each_dpcm_be(rtd, stream, dpcm) { @@ -230,10 +230,19 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, return -EINVAL; } - if (asrc->asrc_width == 16) + width = snd_pcm_format_physical_width(asrc->asrc_format); + if (width < 8 || width > 64) + return -EINVAL; + else if (width == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (width == 16) buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; - else + else if (width == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (width <= 32) buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; config_be.direction = DMA_DEV_TO_DEV; config_be.src_addr_width = buswidth; From be7bd03f0201b5a513ced98c08444a140eab92ea Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 16 Apr 2020 20:25:35 +0800 Subject: [PATCH 084/428] ASoC: fsl_asrc: Move common definition to fsl_asrc_common There is a new ASRC included in i.MX serial platform, there are some common definition can be shared with each other. So move the common definition to a separate header file. And add fsl_asrc_pair_priv and fsl_asrc_priv for the variable specific for the module, which can be used internally. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/7106993928ea9e9720e6b42ec601871103155b1c.1587038908.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 82 +++++++++++++++--------- sound/soc/fsl/fsl_asrc.h | 74 ++-------------------- sound/soc/fsl/fsl_asrc_common.h | 106 ++++++++++++++++++++++++++++++++ sound/soc/fsl/fsl_asrc_dma.c | 25 ++++---- 4 files changed, 178 insertions(+), 109 deletions(-) create mode 100644 sound/soc/fsl/fsl_asrc_common.h diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index a9458fe268bc..067a54ab554f 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -308,8 +308,10 @@ static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, */ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) { - struct asrc_config *config = pair->config; + struct fsl_asrc_pair_priv *pair_priv = pair->private; + struct asrc_config *config = pair_priv->config; struct fsl_asrc *asrc = pair->asrc; + struct fsl_asrc_priv *asrc_priv = asrc->private; enum asrc_pair_index index = pair->index; enum asrc_word_width input_word_width; enum asrc_word_width output_word_width; @@ -392,11 +394,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) } /* Validate input and output clock sources */ - clk_index[IN] = asrc->clk_map[IN][config->inclk]; - clk_index[OUT] = asrc->clk_map[OUT][config->outclk]; + clk_index[IN] = asrc_priv->clk_map[IN][config->inclk]; + clk_index[OUT] = asrc_priv->clk_map[OUT][config->outclk]; /* We only have output clock for ideal ratio mode */ - clk = asrc->asrck_clk[clk_index[ideal ? OUT : IN]]; + clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]]; clk_rate = clk_get_rate(clk); rem[IN] = do_div(clk_rate, inrate); @@ -417,7 +419,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) div[IN] = min_t(u32, 1024, div[IN]); - clk = asrc->asrck_clk[clk_index[OUT]]; + clk = asrc_priv->asrck_clk[clk_index[OUT]]; clk_rate = clk_get_rate(clk); if (ideal && use_ideal_rate) rem[OUT] = do_div(clk_rate, IDEAL_RATIO_RATE); @@ -437,13 +439,13 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) /* Set the channel number */ channels = config->channel_num; - if (asrc->soc->channel_bits < 4) + if (asrc_priv->soc->channel_bits < 4) channels /= 2; /* Update channels for current pair */ regmap_update_bits(asrc->regmap, REG_ASRCNCR, - ASRCNCR_ANCi_MASK(index, asrc->soc->channel_bits), - ASRCNCR_ANCi(index, channels, asrc->soc->channel_bits)); + ASRCNCR_ANCi_MASK(index, asrc_priv->soc->channel_bits), + ASRCNCR_ANCi(index, channels, asrc_priv->soc->channel_bits)); /* Default setting: Automatic selection for processing mode */ regmap_update_bits(asrc->regmap, REG_ASRCTR, @@ -568,9 +570,10 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai); + struct fsl_asrc_priv *asrc_priv = asrc->private; /* Odd channel number is not valid for older ASRC (channel_bits==3) */ - if (asrc->soc->channel_bits == 3) + if (asrc_priv->soc->channel_bits == 3) snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); @@ -586,6 +589,7 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai); struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; + struct fsl_asrc_pair_priv *pair_priv = pair->private; unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); struct asrc_config config; @@ -597,7 +601,7 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, return ret; } - pair->config = &config; + pair_priv->config = &config; config.pair = pair->index; config.channel_num = channels; @@ -931,9 +935,15 @@ static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static int fsl_asrc_get_fifo_addr(u8 dir, enum asrc_pair_index index) +{ + return REG_ASRDx(dir, index); +} + static int fsl_asrc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + struct fsl_asrc_priv *asrc_priv; struct fsl_asrc *asrc; struct resource *res; void __iomem *regs; @@ -946,7 +956,12 @@ static int fsl_asrc_probe(struct platform_device *pdev) if (!asrc) return -ENOMEM; + asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL); + if (!asrc_priv) + return -ENOMEM; + asrc->pdev = pdev; + asrc->private = asrc_priv; /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -992,25 +1007,32 @@ static int fsl_asrc_probe(struct platform_device *pdev) for (i = 0; i < ASRC_CLK_MAX_NUM; i++) { sprintf(tmp, "asrck_%x", i); - asrc->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp); - if (IS_ERR(asrc->asrck_clk[i])) { + asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp); + if (IS_ERR(asrc_priv->asrck_clk[i])) { dev_err(&pdev->dev, "failed to get %s clock\n", tmp); - return PTR_ERR(asrc->asrck_clk[i]); + return PTR_ERR(asrc_priv->asrck_clk[i]); } } - asrc->soc = of_device_get_match_data(&pdev->dev); - if (!asrc->soc) { + asrc_priv->soc = of_device_get_match_data(&pdev->dev); + if (!asrc_priv->soc) { dev_err(&pdev->dev, "failed to get soc data\n"); return -ENODEV; } + asrc->use_edma = asrc_priv->soc->use_edma; + asrc->get_dma_channel = fsl_asrc_get_dma_channel; + asrc->request_pair = fsl_asrc_request_pair; + asrc->release_pair = fsl_asrc_release_pair; + asrc->get_fifo_addr = fsl_asrc_get_fifo_addr; + asrc->pair_priv_size = sizeof(struct fsl_asrc_pair_priv); + if (of_device_is_compatible(np, "fsl,imx35-asrc")) { - asrc->clk_map[IN] = input_clk_map_imx35; - asrc->clk_map[OUT] = output_clk_map_imx35; + asrc_priv->clk_map[IN] = input_clk_map_imx35; + asrc_priv->clk_map[OUT] = output_clk_map_imx35; } else if (of_device_is_compatible(np, "fsl,imx53-asrc")) { - asrc->clk_map[IN] = input_clk_map_imx53; - asrc->clk_map[OUT] = output_clk_map_imx53; + asrc_priv->clk_map[IN] = input_clk_map_imx53; + asrc_priv->clk_map[OUT] = output_clk_map_imx53; } else if (of_device_is_compatible(np, "fsl,imx8qm-asrc") || of_device_is_compatible(np, "fsl,imx8qxp-asrc")) { ret = of_property_read_u32(np, "fsl,asrc-clk-map", &map_idx); @@ -1024,11 +1046,11 @@ static int fsl_asrc_probe(struct platform_device *pdev) return -EINVAL; } if (of_device_is_compatible(np, "fsl,imx8qm-asrc")) { - asrc->clk_map[IN] = clk_map_imx8qm[map_idx]; - asrc->clk_map[OUT] = clk_map_imx8qm[map_idx]; + asrc_priv->clk_map[IN] = clk_map_imx8qm[map_idx]; + asrc_priv->clk_map[OUT] = clk_map_imx8qm[map_idx]; } else { - asrc->clk_map[IN] = clk_map_imx8qxp[map_idx]; - asrc->clk_map[OUT] = clk_map_imx8qxp[map_idx]; + asrc_priv->clk_map[IN] = clk_map_imx8qxp[map_idx]; + asrc_priv->clk_map[OUT] = clk_map_imx8qxp[map_idx]; } } @@ -1093,6 +1115,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) static int fsl_asrc_runtime_resume(struct device *dev) { struct fsl_asrc *asrc = dev_get_drvdata(dev); + struct fsl_asrc_priv *asrc_priv = asrc->private; int i, ret; ret = clk_prepare_enable(asrc->mem_clk); @@ -1107,7 +1130,7 @@ static int fsl_asrc_runtime_resume(struct device *dev) goto disable_ipg_clk; } for (i = 0; i < ASRC_CLK_MAX_NUM; i++) { - ret = clk_prepare_enable(asrc->asrck_clk[i]); + ret = clk_prepare_enable(asrc_priv->asrck_clk[i]); if (ret) goto disable_asrck_clk; } @@ -1116,7 +1139,7 @@ static int fsl_asrc_runtime_resume(struct device *dev) disable_asrck_clk: for (i--; i >= 0; i--) - clk_disable_unprepare(asrc->asrck_clk[i]); + clk_disable_unprepare(asrc_priv->asrck_clk[i]); if (!IS_ERR(asrc->spba_clk)) clk_disable_unprepare(asrc->spba_clk); disable_ipg_clk: @@ -1129,10 +1152,11 @@ disable_mem_clk: static int fsl_asrc_runtime_suspend(struct device *dev) { struct fsl_asrc *asrc = dev_get_drvdata(dev); + struct fsl_asrc_priv *asrc_priv = asrc->private; int i; for (i = 0; i < ASRC_CLK_MAX_NUM; i++) - clk_disable_unprepare(asrc->asrck_clk[i]); + clk_disable_unprepare(asrc_priv->asrck_clk[i]); if (!IS_ERR(asrc->spba_clk)) clk_disable_unprepare(asrc->spba_clk); clk_disable_unprepare(asrc->ipg_clk); @@ -1146,9 +1170,10 @@ static int fsl_asrc_runtime_suspend(struct device *dev) static int fsl_asrc_suspend(struct device *dev) { struct fsl_asrc *asrc = dev_get_drvdata(dev); + struct fsl_asrc_priv *asrc_priv = asrc->private; regmap_read(asrc->regmap, REG_ASRCFG, - &asrc->regcache_cfg); + &asrc_priv->regcache_cfg); regcache_cache_only(asrc->regmap, true); regcache_mark_dirty(asrc->regmap); @@ -1159,6 +1184,7 @@ static int fsl_asrc_suspend(struct device *dev) static int fsl_asrc_resume(struct device *dev) { struct fsl_asrc *asrc = dev_get_drvdata(dev); + struct fsl_asrc_priv *asrc_priv = asrc->private; u32 asrctr; /* Stop all pairs provisionally */ @@ -1172,7 +1198,7 @@ static int fsl_asrc_resume(struct device *dev) regmap_update_bits(asrc->regmap, REG_ASRCFG, ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK | - ASRCFG_PREMODi_ALL_MASK, asrc->regcache_cfg); + ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg); /* Restart enabled pairs */ regmap_update_bits(asrc->regmap, REG_ASRCTR, diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h index 3b0f156af2c3..86d2422ad606 100644 --- a/sound/soc/fsl/fsl_asrc.h +++ b/sound/soc/fsl/fsl_asrc.h @@ -10,8 +10,7 @@ #ifndef _FSL_ASRC_H #define _FSL_ASRC_H -#define IN 0 -#define OUT 1 +#include "fsl_asrc_common.h" #define ASRC_DMA_BUFFER_NUM 2 #define ASRC_INPUTFIFO_THRESHOLD 32 @@ -283,14 +282,6 @@ #define ASRMCR1i_OW16_MASK (1 << ASRMCR1i_OW16_SHIFT) #define ASRMCR1i_OW16(v) ((v) << ASRMCR1i_OW16_SHIFT) - -enum asrc_pair_index { - ASRC_INVALID_PAIR = -1, - ASRC_PAIR_A = 0, - ASRC_PAIR_B = 1, - ASRC_PAIR_C = 2, -}; - #define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1) enum asrc_inclk { @@ -446,83 +437,28 @@ struct fsl_asrc_soc_data { }; /** - * fsl_asrc_pair: ASRC Pair private data + * fsl_asrc_pair_priv: ASRC Pair private data * - * @asrc: pointer to its parent module * @config: configuration profile - * @error: error record - * @index: pair index (ASRC_PAIR_A, ASRC_PAIR_B, ASRC_PAIR_C) - * @channels: occupied channel number - * @desc: input and output dma descriptors - * @dma_chan: inputer and output DMA channels - * @dma_data: private dma data - * @pos: hardware pointer position - * @private: pair private area */ -struct fsl_asrc_pair { - struct fsl_asrc *asrc; +struct fsl_asrc_pair_priv { struct asrc_config *config; - unsigned int error; - - enum asrc_pair_index index; - unsigned int channels; - - struct dma_async_tx_descriptor *desc[2]; - struct dma_chan *dma_chan[2]; - struct imx_dma_data dma_data; - unsigned int pos; - - void *private; }; /** - * fsl_asrc_pair: ASRC private data + * fsl_asrc_priv: ASRC private data * - * @dma_params_rx: DMA parameters for receive channel - * @dma_params_tx: DMA parameters for transmit channel - * @pdev: platform device pointer - * @regmap: regmap handler - * @paddr: physical address to the base address of registers - * @mem_clk: clock source to access register - * @ipg_clk: clock source to drive peripheral - * @spba_clk: SPBA clock (optional, depending on SoC design) * @asrck_clk: clock sources to driver ASRC internal logic - * @lock: spin lock for resource protection - * @pair: pair pointers * @soc: soc specific data - * @channel_avail: non-occupied channel numbers * @clk_map: clock map for input/output clock - * @asrc_rate: default sample rate for ASoC Back-Ends - * @asrc_format: default sample format for ASoC Back-Ends * @regcache_cfg: store register value of REG_ASRCFG */ -struct fsl_asrc { - struct snd_dmaengine_dai_dma_data dma_params_rx; - struct snd_dmaengine_dai_dma_data dma_params_tx; - struct platform_device *pdev; - struct regmap *regmap; - unsigned long paddr; - struct clk *mem_clk; - struct clk *ipg_clk; - struct clk *spba_clk; +struct fsl_asrc_priv { struct clk *asrck_clk[ASRC_CLK_MAX_NUM]; - spinlock_t lock; - - struct fsl_asrc_pair *pair[ASRC_PAIR_MAX_NUM]; const struct fsl_asrc_soc_data *soc; - unsigned int channel_avail; unsigned char *clk_map[2]; - int asrc_rate; - snd_pcm_format_t asrc_format; - u32 regcache_cfg; }; -#define DRV_NAME "fsl-asrc-dai" -extern struct snd_soc_component_driver fsl_asrc_component; -struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir); -int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair); -void fsl_asrc_release_pair(struct fsl_asrc_pair *pair); - #endif /* _FSL_ASRC_H */ diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h new file mode 100644 index 000000000000..77665b15c8db --- /dev/null +++ b/sound/soc/fsl/fsl_asrc_common.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 NXP + * + */ + +#ifndef _FSL_ASRC_COMMON_H +#define _FSL_ASRC_COMMON_H + +/* directions */ +#define IN 0 +#define OUT 1 + +enum asrc_pair_index { + ASRC_INVALID_PAIR = -1, + ASRC_PAIR_A = 0, + ASRC_PAIR_B = 1, + ASRC_PAIR_C = 2, + ASRC_PAIR_D = 3, +}; + +#define PAIR_CTX_NUM 0x4 + +/** + * fsl_asrc_pair: ASRC Pair common data + * + * @asrc: pointer to its parent module + * @error: error record + * @index: pair index (ASRC_PAIR_A, ASRC_PAIR_B, ASRC_PAIR_C) + * @channels: occupied channel number + * @desc: input and output dma descriptors + * @dma_chan: inputer and output DMA channels + * @dma_data: private dma data + * @pos: hardware pointer position + * @private: pair private area + */ +struct fsl_asrc_pair { + struct fsl_asrc *asrc; + unsigned int error; + + enum asrc_pair_index index; + unsigned int channels; + + struct dma_async_tx_descriptor *desc[2]; + struct dma_chan *dma_chan[2]; + struct imx_dma_data dma_data; + unsigned int pos; + + void *private; +}; + +/** + * fsl_asrc: ASRC common data + * + * @dma_params_rx: DMA parameters for receive channel + * @dma_params_tx: DMA parameters for transmit channel + * @pdev: platform device pointer + * @regmap: regmap handler + * @paddr: physical address to the base address of registers + * @mem_clk: clock source to access register + * @ipg_clk: clock source to drive peripheral + * @spba_clk: SPBA clock (optional, depending on SoC design) + * @lock: spin lock for resource protection + * @pair: pair pointers + * @channel_avail: non-occupied channel numbers + * @asrc_rate: default sample rate for ASoC Back-Ends + * @asrc_format: default sample format for ASoC Back-Ends + * @use_edma: edma is used + * @get_dma_channel: function pointer + * @request_pair: function pointer + * @release_pair: function pointer + * @get_fifo_addr: function pointer + * @pair_priv_size: size of pair private struct. + * @private: private data structure + */ +struct fsl_asrc { + struct snd_dmaengine_dai_dma_data dma_params_rx; + struct snd_dmaengine_dai_dma_data dma_params_tx; + struct platform_device *pdev; + struct regmap *regmap; + unsigned long paddr; + struct clk *mem_clk; + struct clk *ipg_clk; + struct clk *spba_clk; + spinlock_t lock; /* spin lock for resource protection */ + + struct fsl_asrc_pair *pair[PAIR_CTX_NUM]; + unsigned int channel_avail; + + int asrc_rate; + snd_pcm_format_t asrc_format; + bool use_edma; + + struct dma_chan *(*get_dma_channel)(struct fsl_asrc_pair *pair, bool dir); + int (*request_pair)(int channels, struct fsl_asrc_pair *pair); + void (*release_pair)(struct fsl_asrc_pair *pair); + int (*get_fifo_addr)(u8 dir, enum asrc_pair_index index); + size_t pair_priv_size; + + void *private; +}; + +#define DRV_NAME "fsl-asrc-dai" +extern struct snd_soc_component_driver fsl_asrc_component; + +#endif /* _FSL_ASRC_COMMON_H */ diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index a9dd3155ff35..e5d1b218acf8 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -12,7 +12,7 @@ #include #include -#include "fsl_asrc.h" +#include "fsl_asrc_common.h" #define FSL_ASRC_DMABUF_SIZE (256 * 1024) @@ -170,10 +170,10 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, /* Override dma_data of the Front-End and config its dmaengine */ dma_params_fe = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); - dma_params_fe->addr = asrc->paddr + REG_ASRDx(!dir, index); + dma_params_fe->addr = asrc->paddr + asrc->get_fifo_addr(!dir, index); dma_params_fe->maxburst = dma_params_be->maxburst; - pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir); + pair->dma_chan[!dir] = asrc->get_dma_channel(pair, !dir); if (!pair->dma_chan[!dir]) { dev_err(dev, "failed to request DMA channel\n"); return -EINVAL; @@ -203,7 +203,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, * need to configure dma_request and dma_request2, but get dma_chan via * dma_request_slave_channel directly with dma name of Front-End device */ - if (!asrc->soc->use_edma) { + if (!asrc->use_edma) { /* Get DMA request of Back-End */ tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx"); tmp_data = tmp_chan->private; @@ -211,7 +211,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, dma_release_channel(tmp_chan); /* Get DMA request of Front-End */ - tmp_chan = fsl_asrc_get_dma_channel(pair, dir); + tmp_chan = asrc->get_dma_channel(pair, dir); tmp_data = tmp_chan->private; pair->dma_data.dma_request2 = tmp_data->dma_request; pair->dma_data.peripheral_type = tmp_data->peripheral_type; @@ -222,7 +222,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, dma_request_channel(mask, filter, &pair->dma_data); } else { pair->dma_chan[dir] = - fsl_asrc_get_dma_channel(pair, dir); + asrc->get_dma_channel(pair, dir); } if (!pair->dma_chan[dir]) { @@ -251,10 +251,10 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, config_be.dst_maxburst = dma_params_be->maxburst; if (tx) { - config_be.src_addr = asrc->paddr + REG_ASRDO(index); + config_be.src_addr = asrc->paddr + asrc->get_fifo_addr(OUT, index); config_be.dst_addr = dma_params_be->addr; } else { - config_be.dst_addr = asrc->paddr + REG_ASRDI(index); + config_be.dst_addr = asrc->paddr + asrc->get_fifo_addr(IN, index); config_be.src_addr = dma_params_be->addr; } @@ -311,11 +311,12 @@ static int fsl_asrc_dma_startup(struct snd_soc_component *component, return ret; } - pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL); + pair = kzalloc(sizeof(*pair) + asrc->pair_priv_size, GFP_KERNEL); if (!pair) return -ENOMEM; pair->asrc = asrc; + pair->private = (void *)pair + sizeof(struct fsl_asrc_pair); runtime->private_data = pair; @@ -323,14 +324,14 @@ static int fsl_asrc_dma_startup(struct snd_soc_component *component, * Request pair function needs channel num as input, for this * dummy pair, we just request "1" channel temporarily. */ - ret = fsl_asrc_request_pair(1, pair); + ret = asrc->request_pair(1, pair); if (ret < 0) { dev_err(dev, "failed to request asrc pair\n"); goto req_pair_err; } /* Request a dummy dma channel, which will be released later. */ - tmp_chan = fsl_asrc_get_dma_channel(pair, dir); + tmp_chan = asrc->get_dma_channel(pair, dir); if (!tmp_chan) { dev_err(dev, "failed to get dma channel\n"); ret = -EINVAL; @@ -356,7 +357,7 @@ out: dma_release_channel(tmp_chan); dma_chan_err: - fsl_asrc_release_pair(pair); + asrc->release_pair(pair); req_pair_err: if (release_pair) From a960de4da241d409a73e318ab19e6b5fdcd95a83 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 16 Apr 2020 20:25:36 +0800 Subject: [PATCH 085/428] ASoC: dt-bindings: fsl_easrc: Add document for EASRC EASRC (Enhanced Asynchronous Sample Rate Converter) is a new IP module found on i.MX8MN. Signed-off-by: Shengjiu Wang Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/3195cad960113a089d63c10e2268d63b253a69c5.1587038908.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,easrc.yaml | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/fsl,easrc.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl,easrc.yaml b/Documentation/devicetree/bindings/sound/fsl,easrc.yaml new file mode 100644 index 000000000000..73cdcf053a9c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,easrc.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,easrc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP Asynchronous Sample Rate Converter (ASRC) Controller + +maintainers: + - Shengjiu Wang + +properties: + $nodename: + pattern: "^easrc@.*" + + compatible: + const: fsl,imx8mn-easrc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Peripheral clock + + clock-names: + items: + - const: mem + + dmas: + maxItems: 8 + + dma-names: + items: + - const: ctx0_rx + - const: ctx0_tx + - const: ctx1_rx + - const: ctx1_tx + - const: ctx2_rx + - const: ctx2_tx + - const: ctx3_rx + - const: ctx3_tx + + firmware-name: + allOf: + - $ref: /schemas/types.yaml#/definitions/string + - const: imx/easrc/easrc-imx8mn.bin + description: The coefficient table for the filters + + fsl,asrc-rate: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - minimum: 8000 + - maximum: 192000 + description: Defines a mutual sample rate used by DPCM Back Ends + + fsl,asrc-format: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [2, 6, 10, 32, 36] + default: 2 + description: + Defines a mutual sample format used by DPCM Back Ends + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - dmas + - dma-names + - firmware-name + - fsl,asrc-rate + - fsl,asrc-format + +examples: + - | + #include + + easrc: easrc@300c0000 { + compatible = "fsl,imx8mn-easrc"; + reg = <0x0 0x300c0000 0x0 0x10000>; + interrupts = <0x0 122 0x4>; + clocks = <&clk IMX8MN_CLK_ASRC_ROOT>; + clock-names = "mem"; + dmas = <&sdma2 16 23 0> , <&sdma2 17 23 0>, + <&sdma2 18 23 0> , <&sdma2 19 23 0>, + <&sdma2 20 23 0> , <&sdma2 21 23 0>, + <&sdma2 22 23 0> , <&sdma2 23 23 0>; + dma-names = "ctx0_rx", "ctx0_tx", + "ctx1_rx", "ctx1_tx", + "ctx2_rx", "ctx2_tx", + "ctx3_rx", "ctx3_tx"; + firmware-name = "imx/easrc/easrc-imx8mn.bin"; + fsl,asrc-rate = <8000>; + fsl,asrc-format = <2>; + }; From 955ac624058f91172b3b8820280556e699e1e0ff Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 16 Apr 2020 20:25:37 +0800 Subject: [PATCH 086/428] ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers EASRC (Enhanced Asynchronous Sample Rate Converter) is a new IP module found on i.MX8MN. It is different with old ASRC module. The primary features for the EASRC are as follows: - 4 Contexts - groups of channels with an independent time base - Fully independent and concurrent context control - Simultaneous processing of up to 32 audio channels - Programmable filter charachteristics for each context - 32, 24, 20, and 16-bit fixed point audio sample support - 32-bit floating point audio sample support - 8kHz to 384kHz sample rate - 1/16 to 8x sample rate conversion ratio Signed-off-by: Shengjiu Wang Signed-off-by: Cosmin-Gabriel Samoila Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/260d7a9fbddf9fa90760d30095df60a4c25fd0a1.1587038908.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 11 + sound/soc/fsl/Makefile | 2 + sound/soc/fsl/fsl_easrc.c | 2114 +++++++++++++++++++++++++++++++++++++ sound/soc/fsl/fsl_easrc.h | 651 ++++++++++++ 4 files changed, 2778 insertions(+) create mode 100644 sound/soc/fsl/fsl_easrc.c create mode 100644 sound/soc/fsl/fsl_easrc.h diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 65e8cd4be930..ea7b4787a8af 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -84,6 +84,17 @@ config SND_SOC_FSL_MICFIL Say Y if you want to add Pulse Density Modulation microphone interface (MICFIL) support for NXP. +config SND_SOC_FSL_EASRC + tristate "Enhanced Asynchronous Sample Rate Converter (EASRC) module support" + depends on SND_SOC_FSL_ASRC + select REGMAP_MMIO + select SND_SOC_GENERIC_DMAENGINE_PCM + help + Say Y if you want to add Enhanced ASRC support for NXP. The ASRC is + a digital module that converts audio from a source sample rate to a + destination sample rate. It is a new design module compare with the + old ASRC. + config SND_SOC_FSL_UTILS tristate diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 8cde88c72d93..b835eebf8825 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -24,6 +24,7 @@ snd-soc-fsl-micfil-objs := fsl_micfil.o snd-soc-fsl-utils-objs := fsl_utils.o snd-soc-fsl-dma-objs := fsl_dma.o snd-soc-fsl-mqs-objs := fsl_mqs.o +snd-soc-fsl-easrc-objs := fsl_easrc.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 @@ -35,6 +36,7 @@ obj-$(CONFIG_SND_SOC_FSL_ESAI) += snd-soc-fsl-esai.o obj-$(CONFIG_SND_SOC_FSL_MICFIL) += snd-soc-fsl-micfil.o obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o obj-$(CONFIG_SND_SOC_FSL_MQS) += snd-soc-fsl-mqs.o +obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o # MPC5200 Platform Support diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c new file mode 100644 index 000000000000..233f26ff885c --- /dev/null +++ b/sound/soc/fsl/fsl_easrc.c @@ -0,0 +1,2114 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright 2019 NXP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fsl_easrc.h" +#include "imx-pcm.h" + +#define FSL_EASRC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_U16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ + SNDRV_PCM_FMTBIT_U24_LE | \ + SNDRV_PCM_FMTBIT_U24_3LE | \ + SNDRV_PCM_FMTBIT_S32_LE | \ + SNDRV_PCM_FMTBIT_U32_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_U20_3LE | \ + SNDRV_PCM_FMTBIT_FLOAT_LE) + +static int fsl_easrc_iec958_put_bits(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct fsl_asrc *easrc = snd_soc_component_get_drvdata(comp); + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct soc_mreg_control *mc = + (struct soc_mreg_control *)kcontrol->private_value; + unsigned int regval = ucontrol->value.integer.value[0]; + + easrc_priv->bps_iec958[mc->regbase] = regval; + + return 0; +} + +static int fsl_easrc_iec958_get_bits(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct fsl_asrc *easrc = snd_soc_component_get_drvdata(comp); + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct soc_mreg_control *mc = + (struct soc_mreg_control *)kcontrol->private_value; + + ucontrol->value.enumerated.item[0] = easrc_priv->bps_iec958[mc->regbase]; + + return 0; +} + +static int fsl_easrc_get_reg(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_mreg_control *mc = + (struct soc_mreg_control *)kcontrol->private_value; + unsigned int regval; + int ret; + + ret = snd_soc_component_read(component, mc->regbase, ®val); + if (ret < 0) + return ret; + + ucontrol->value.integer.value[0] = regval; + + return 0; +} + +static int fsl_easrc_set_reg(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_mreg_control *mc = + (struct soc_mreg_control *)kcontrol->private_value; + unsigned int regval = ucontrol->value.integer.value[0]; + int ret; + + ret = snd_soc_component_write(component, mc->regbase, regval); + if (ret < 0) + return ret; + + return 0; +} + +#define SOC_SINGLE_REG_RW(xname, xreg) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = snd_soc_info_xr_sx, .get = fsl_easrc_get_reg, \ + .put = fsl_easrc_set_reg, \ + .private_value = (unsigned long)&(struct soc_mreg_control) \ + { .regbase = xreg, .regcount = 1, .nbits = 32, \ + .invert = 0, .min = 0, .max = 0xffffffff, } } + +#define SOC_SINGLE_VAL_RW(xname, xreg) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = snd_soc_info_xr_sx, .get = fsl_easrc_iec958_get_bits, \ + .put = fsl_easrc_iec958_put_bits, \ + .private_value = (unsigned long)&(struct soc_mreg_control) \ + { .regbase = xreg, .regcount = 1, .nbits = 32, \ + .invert = 0, .min = 0, .max = 2, } } + +static const struct snd_kcontrol_new fsl_easrc_snd_controls[] = { + SOC_SINGLE("Context 0 Dither Switch", REG_EASRC_COC(0), 0, 1, 0), + SOC_SINGLE("Context 1 Dither Switch", REG_EASRC_COC(1), 0, 1, 0), + SOC_SINGLE("Context 2 Dither Switch", REG_EASRC_COC(2), 0, 1, 0), + SOC_SINGLE("Context 3 Dither Switch", REG_EASRC_COC(3), 0, 1, 0), + + SOC_SINGLE("Context 0 IEC958 Validity", REG_EASRC_COC(0), 2, 1, 0), + SOC_SINGLE("Context 1 IEC958 Validity", REG_EASRC_COC(1), 2, 1, 0), + SOC_SINGLE("Context 2 IEC958 Validity", REG_EASRC_COC(2), 2, 1, 0), + SOC_SINGLE("Context 3 IEC958 Validity", REG_EASRC_COC(3), 2, 1, 0), + + SOC_SINGLE_VAL_RW("Context 0 IEC958 Bits Per Sample", 0), + SOC_SINGLE_VAL_RW("Context 1 IEC958 Bits Per Sample", 1), + SOC_SINGLE_VAL_RW("Context 2 IEC958 Bits Per Sample", 2), + SOC_SINGLE_VAL_RW("Context 3 IEC958 Bits Per Sample", 3), + + SOC_SINGLE_REG_RW("Context 0 IEC958 CS0", REG_EASRC_CS0(0)), + SOC_SINGLE_REG_RW("Context 1 IEC958 CS0", REG_EASRC_CS0(1)), + SOC_SINGLE_REG_RW("Context 2 IEC958 CS0", REG_EASRC_CS0(2)), + SOC_SINGLE_REG_RW("Context 3 IEC958 CS0", REG_EASRC_CS0(3)), + SOC_SINGLE_REG_RW("Context 0 IEC958 CS1", REG_EASRC_CS1(0)), + SOC_SINGLE_REG_RW("Context 1 IEC958 CS1", REG_EASRC_CS1(1)), + SOC_SINGLE_REG_RW("Context 2 IEC958 CS1", REG_EASRC_CS1(2)), + SOC_SINGLE_REG_RW("Context 3 IEC958 CS1", REG_EASRC_CS1(3)), + SOC_SINGLE_REG_RW("Context 0 IEC958 CS2", REG_EASRC_CS2(0)), + SOC_SINGLE_REG_RW("Context 1 IEC958 CS2", REG_EASRC_CS2(1)), + SOC_SINGLE_REG_RW("Context 2 IEC958 CS2", REG_EASRC_CS2(2)), + SOC_SINGLE_REG_RW("Context 3 IEC958 CS2", REG_EASRC_CS2(3)), + SOC_SINGLE_REG_RW("Context 0 IEC958 CS3", REG_EASRC_CS3(0)), + SOC_SINGLE_REG_RW("Context 1 IEC958 CS3", REG_EASRC_CS3(1)), + SOC_SINGLE_REG_RW("Context 2 IEC958 CS3", REG_EASRC_CS3(2)), + SOC_SINGLE_REG_RW("Context 3 IEC958 CS3", REG_EASRC_CS3(3)), + SOC_SINGLE_REG_RW("Context 0 IEC958 CS4", REG_EASRC_CS4(0)), + SOC_SINGLE_REG_RW("Context 1 IEC958 CS4", REG_EASRC_CS4(1)), + SOC_SINGLE_REG_RW("Context 2 IEC958 CS4", REG_EASRC_CS4(2)), + SOC_SINGLE_REG_RW("Context 3 IEC958 CS4", REG_EASRC_CS4(3)), + SOC_SINGLE_REG_RW("Context 0 IEC958 CS5", REG_EASRC_CS5(0)), + SOC_SINGLE_REG_RW("Context 1 IEC958 CS5", REG_EASRC_CS5(1)), + SOC_SINGLE_REG_RW("Context 2 IEC958 CS5", REG_EASRC_CS5(2)), + SOC_SINGLE_REG_RW("Context 3 IEC958 CS5", REG_EASRC_CS5(3)), +}; + +/* + * fsl_easrc_set_rs_ratio + * + * According to the resample taps, calculate the resample ratio + * ratio = in_rate / out_rate + */ +static int fsl_easrc_set_rs_ratio(struct fsl_asrc_pair *ctx) +{ + struct fsl_asrc *easrc = ctx->asrc; + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; + unsigned int in_rate = ctx_priv->in_params.norm_rate; + unsigned int out_rate = ctx_priv->out_params.norm_rate; + unsigned int int_bits; + unsigned int frac_bits; + u64 val; + u32 *r; + + switch (easrc_priv->rs_num_taps) { + case EASRC_RS_32_TAPS: + int_bits = 5; + frac_bits = 39; + break; + case EASRC_RS_64_TAPS: + int_bits = 6; + frac_bits = 38; + break; + case EASRC_RS_128_TAPS: + int_bits = 7; + frac_bits = 37; + break; + default: + return -EINVAL; + } + + val = (u64)in_rate << frac_bits; + do_div(val, out_rate); + r = (uint32_t *)&val; + + if (r[1] & 0xFFFFF000) { + dev_err(&easrc->pdev->dev, "ratio exceed range\n"); + return -EINVAL; + } + + regmap_write(easrc->regmap, REG_EASRC_RRL(ctx->index), + EASRC_RRL_RS_RL(r[0])); + regmap_write(easrc->regmap, REG_EASRC_RRH(ctx->index), + EASRC_RRH_RS_RH(r[1])); + + return 0; +} + +/* Normalize input and output sample rates */ +static void fsl_easrc_normalize_rates(struct fsl_asrc_pair *ctx) +{ + struct fsl_easrc_ctx_priv *ctx_priv; + int a, b; + + if (!ctx) + return; + + ctx_priv = ctx->private; + + a = ctx_priv->in_params.sample_rate; + b = ctx_priv->out_params.sample_rate; + + a = gcd(a, b); + + /* Divide by gcd to normalize the rate */ + ctx_priv->in_params.norm_rate = ctx_priv->in_params.sample_rate / a; + ctx_priv->out_params.norm_rate = ctx_priv->out_params.sample_rate / a; +} + +/* Resets the pointer of the coeff memory pointers */ +static int fsl_easrc_coeff_mem_ptr_reset(struct fsl_asrc *easrc, + unsigned int ctx_id, int mem_type) +{ + struct device *dev; + u32 reg, mask, val; + + if (!easrc) + return -ENODEV; + + dev = &easrc->pdev->dev; + + switch (mem_type) { + case EASRC_PF_COEFF_MEM: + /* This resets the prefilter memory pointer addr */ + if (ctx_id >= EASRC_CTX_MAX_NUM) { + dev_err(dev, "Invalid context id[%d]\n", ctx_id); + return -EINVAL; + } + + reg = REG_EASRC_CCE1(ctx_id); + mask = EASRC_CCE1_COEF_MEM_RST_MASK; + val = EASRC_CCE1_COEF_MEM_RST; + break; + case EASRC_RS_COEFF_MEM: + /* This resets the resampling memory pointer addr */ + reg = REG_EASRC_CRCC; + mask = EASRC_CRCC_RS_CPR_MASK; + val = EASRC_CRCC_RS_CPR; + break; + default: + dev_err(dev, "Unknown memory type\n"); + return -EINVAL; + } + + /* + * To reset the write pointer back to zero, the register field + * ASRC_CTX_CTRL_EXT1x[PF_COEFF_MEM_RST] can be toggled from + * 0x0 to 0x1 to 0x0. + */ + regmap_update_bits(easrc->regmap, reg, mask, 0); + regmap_update_bits(easrc->regmap, reg, mask, val); + regmap_update_bits(easrc->regmap, reg, mask, 0); + + return 0; +} + +static inline uint32_t bits_taps_to_val(unsigned int t) +{ + switch (t) { + case EASRC_RS_32_TAPS: + return 32; + case EASRC_RS_64_TAPS: + return 64; + case EASRC_RS_128_TAPS: + return 128; + } + + return 0; +} + +static int fsl_easrc_resampler_config(struct fsl_asrc *easrc) +{ + struct device *dev = &easrc->pdev->dev; + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct asrc_firmware_hdr *hdr = easrc_priv->firmware_hdr; + struct interp_params *interp = easrc_priv->interp; + struct interp_params *selected_interp = NULL; + unsigned int num_coeff; + unsigned int i; + u64 *coef; + u32 *r; + int ret; + + if (!hdr) { + dev_err(dev, "firmware not loaded!\n"); + return -ENODEV; + } + + for (i = 0; i < hdr->interp_scen; i++) { + if ((interp[i].num_taps - 1) != + bits_taps_to_val(easrc_priv->rs_num_taps)) + continue; + + coef = interp[i].coeff; + selected_interp = &interp[i]; + dev_dbg(dev, "Selected interp_filter: %u taps - %u phases\n", + selected_interp->num_taps, + selected_interp->num_phases); + break; + } + + if (!selected_interp) { + dev_err(dev, "failed to get interpreter configuration\n"); + return -EINVAL; + } + + /* + * RS_LOW - first half of center tap of the sinc function + * RS_HIGH - second half of center tap of the sinc function + * This is due to the fact the resampling function must be + * symetrical - i.e. odd number of taps + */ + r = (uint32_t *)&selected_interp->center_tap; + regmap_write(easrc->regmap, REG_EASRC_RCTCL, EASRC_RCTCL_RS_CL(r[0])); + regmap_write(easrc->regmap, REG_EASRC_RCTCH, EASRC_RCTCH_RS_CH(r[1])); + + /* + * Write Number of Resampling Coefficient Taps + * 00b - 32-Tap Resampling Filter + * 01b - 64-Tap Resampling Filter + * 10b - 128-Tap Resampling Filter + * 11b - N/A + */ + regmap_update_bits(easrc->regmap, REG_EASRC_CRCC, + EASRC_CRCC_RS_TAPS_MASK, + EASRC_CRCC_RS_TAPS(easrc_priv->rs_num_taps)); + + /* Reset prefilter coefficient pointer back to 0 */ + ret = fsl_easrc_coeff_mem_ptr_reset(easrc, 0, EASRC_RS_COEFF_MEM); + if (ret) + return ret; + + /* + * When the filter is programmed to run in: + * 32-tap mode, 16-taps, 128-phases 4-coefficients per phase + * 64-tap mode, 32-taps, 64-phases 4-coefficients per phase + * 128-tap mode, 64-taps, 32-phases 4-coefficients per phase + * This means the number of writes is constant no matter + * the mode we are using + */ + num_coeff = 16 * 128 * 4; + + for (i = 0; i < num_coeff; i++) { + r = (uint32_t *)&coef[i]; + regmap_write(easrc->regmap, REG_EASRC_CRCM, + EASRC_CRCM_RS_CWD(r[0])); + regmap_write(easrc->regmap, REG_EASRC_CRCM, + EASRC_CRCM_RS_CWD(r[1])); + } + + return 0; +} + +/** + * Scale filter coefficients (64 bits float) + * For input float32 normalized range (1.0,-1.0) -> output int[16,24,32]: + * scale it by multiplying filter coefficients by 2^31 + * For input int[16, 24, 32] -> output float32 + * scale it by multiplying filter coefficients by 2^-15, 2^-23, 2^-31 + * input: + * asrc: Structure pointer of fsl_asrc + * infilter : Pointer to non-scaled input filter + * shift: The multiply factor + * output: + * outfilter: scaled filter + */ +static int fsl_easrc_normalize_filter(struct fsl_asrc *easrc, + u64 *infilter, + u64 *outfilter, + int shift) +{ + struct device *dev = &easrc->pdev->dev; + u64 coef = *infilter; + s64 exp = (coef & 0x7ff0000000000000ll) >> 52; + u64 outcoef; + + /* + * If exponent is zero (value == 0), or 7ff (value == NaNs) + * dont touch the content + */ + if (exp == 0 || exp == 0x7ff) { + *outfilter = coef; + return 0; + } + + /* coef * 2^shift ==> exp + shift */ + exp += shift; + + if ((shift > 0 && exp >= 0x7ff) || (shift < 0 && exp <= 0)) { + dev_err(dev, "coef out of range\n"); + return -EINVAL; + } + + outcoef = (u64)(coef & 0x800FFFFFFFFFFFFFll) + ((u64)exp << 52); + *outfilter = outcoef; + + return 0; +} + +static int fsl_easrc_write_pf_coeff_mem(struct fsl_asrc *easrc, int ctx_id, + u64 *coef, int n_taps, int shift) +{ + struct device *dev = &easrc->pdev->dev; + int ret = 0; + int i; + u32 *r; + u64 tmp; + + /* If STx_NUM_TAPS is set to 0x0 then return */ + if (!n_taps) + return 0; + + if (!coef) { + dev_err(dev, "coef table is NULL\n"); + return -EINVAL; + } + + /* + * When switching between stages, the address pointer + * should be reset back to 0x0 before performing a write + */ + ret = fsl_easrc_coeff_mem_ptr_reset(easrc, ctx_id, EASRC_PF_COEFF_MEM); + if (ret) + return ret; + + for (i = 0; i < (n_taps + 1) / 2; i++) { + ret = fsl_easrc_normalize_filter(easrc, &coef[i], &tmp, shift); + if (ret) + return ret; + + r = (uint32_t *)&tmp; + regmap_write(easrc->regmap, REG_EASRC_PCF(ctx_id), + EASRC_PCF_CD(r[0])); + regmap_write(easrc->regmap, REG_EASRC_PCF(ctx_id), + EASRC_PCF_CD(r[1])); + } + + return 0; +} + +static int fsl_easrc_prefilter_config(struct fsl_asrc *easrc, + unsigned int ctx_id) +{ + struct prefil_params *prefil, *selected_prefil = NULL; + struct fsl_easrc_ctx_priv *ctx_priv; + struct fsl_easrc_priv *easrc_priv; + struct asrc_firmware_hdr *hdr; + struct fsl_asrc_pair *ctx; + struct device *dev; + u32 inrate, outrate, offset = 0; + u32 in_s_rate, out_s_rate, in_s_fmt, out_s_fmt; + int ret, i; + + if (!easrc) + return -ENODEV; + + dev = &easrc->pdev->dev; + + if (ctx_id >= EASRC_CTX_MAX_NUM) { + dev_err(dev, "Invalid context id[%d]\n", ctx_id); + return -EINVAL; + } + + easrc_priv = easrc->private; + + ctx = easrc->pair[ctx_id]; + ctx_priv = ctx->private; + + in_s_rate = ctx_priv->in_params.sample_rate; + out_s_rate = ctx_priv->out_params.sample_rate; + in_s_fmt = ctx_priv->in_params.sample_format; + out_s_fmt = ctx_priv->out_params.sample_format; + + ctx_priv->in_filled_sample = bits_taps_to_val(easrc_priv->rs_num_taps) / 2; + ctx_priv->out_missed_sample = ctx_priv->in_filled_sample * out_s_rate / in_s_rate; + + ctx_priv->st1_num_taps = 0; + ctx_priv->st2_num_taps = 0; + + regmap_write(easrc->regmap, REG_EASRC_CCE1(ctx_id), 0); + regmap_write(easrc->regmap, REG_EASRC_CCE2(ctx_id), 0); + + /* + * The audio float point data range is (-1, 1), the asrc would output + * all zero for float point input and integer output case, that is to + * drop the fractional part of the data directly. + * + * In order to support float to int conversion or int to float + * conversion we need to do special operation on the coefficient to + * enlarge/reduce the data to the expected range. + * + * For float to int case: + * Up sampling: + * 1. Create a 1 tap filter with center tap (only tap) of 2^31 + * in 64 bits floating point. + * double value = (double)(((uint64_t)1) << 31) + * 2. Program 1 tap prefilter with center tap above. + * + * Down sampling, + * 1. If the filter is single stage filter, add "shift" to the exponent + * of stage 1 coefficients. + * 2. If the filter is two stage filter , add "shift" to the exponent + * of stage 2 coefficients. + * + * The "shift" is 31, same for int16, int24, int32 case. + * + * For int to float case: + * Up sampling: + * 1. Create a 1 tap filter with center tap (only tap) of 2^-31 + * in 64 bits floating point. + * 2. Program 1 tap prefilter with center tap above. + * + * Down sampling, + * 1. If the filter is single stage filter, subtract "shift" to the + * exponent of stage 1 coefficients. + * 2. If the filter is two stage filter , subtract "shift" to the + * exponent of stage 2 coefficients. + * + * The "shift" is 15,23,31, different for int16, int24, int32 case. + * + */ + if (out_s_rate >= in_s_rate) { + if (out_s_rate == in_s_rate) + regmap_update_bits(easrc->regmap, + REG_EASRC_CCE1(ctx_id), + EASRC_CCE1_RS_BYPASS_MASK, + EASRC_CCE1_RS_BYPASS); + + ctx_priv->st1_num_taps = 1; + ctx_priv->st1_coeff = &easrc_priv->const_coeff; + ctx_priv->st1_num_exp = 1; + ctx_priv->st2_num_taps = 0; + + if (in_s_fmt == SNDRV_PCM_FORMAT_FLOAT_LE && + out_s_fmt != SNDRV_PCM_FORMAT_FLOAT_LE) + ctx_priv->st1_addexp = 31; + else if (in_s_fmt != SNDRV_PCM_FORMAT_FLOAT_LE && + out_s_fmt == SNDRV_PCM_FORMAT_FLOAT_LE) + ctx_priv->st1_addexp -= ctx_priv->in_params.fmt.addexp; + } else { + inrate = ctx_priv->in_params.norm_rate; + outrate = ctx_priv->out_params.norm_rate; + + hdr = easrc_priv->firmware_hdr; + prefil = easrc_priv->prefil; + + for (i = 0; i < hdr->prefil_scen; i++) { + if (inrate == prefil[i].insr && + outrate == prefil[i].outsr) { + selected_prefil = &prefil[i]; + dev_dbg(dev, "Selected prefilter: %u insr, %u outsr, %u st1_taps, %u st2_taps\n", + selected_prefil->insr, + selected_prefil->outsr, + selected_prefil->st1_taps, + selected_prefil->st2_taps); + break; + } + } + + if (!selected_prefil) { + dev_err(dev, "Conversion from in ratio %u(%u) to out ratio %u(%u) is not supported\n", + in_s_rate, inrate, + out_s_rate, outrate); + return -EINVAL; + } + + /* + * In prefilter coeff array, first st1_num_taps represent the + * stage1 prefilter coefficients followed by next st2_num_taps + * representing stage 2 coefficients + */ + ctx_priv->st1_num_taps = selected_prefil->st1_taps; + ctx_priv->st1_coeff = selected_prefil->coeff; + ctx_priv->st1_num_exp = selected_prefil->st1_exp; + + offset = ((selected_prefil->st1_taps + 1) / 2); + ctx_priv->st2_num_taps = selected_prefil->st2_taps; + ctx_priv->st2_coeff = selected_prefil->coeff + offset; + + if (in_s_fmt == SNDRV_PCM_FORMAT_FLOAT_LE && + out_s_fmt != SNDRV_PCM_FORMAT_FLOAT_LE) { + /* only change stage2 coefficient for 2 stage case */ + if (ctx_priv->st2_num_taps > 0) + ctx_priv->st2_addexp = 31; + else + ctx_priv->st1_addexp = 31; + } else if (in_s_fmt != SNDRV_PCM_FORMAT_FLOAT_LE && + out_s_fmt == SNDRV_PCM_FORMAT_FLOAT_LE) { + if (ctx_priv->st2_num_taps > 0) + ctx_priv->st2_addexp -= ctx_priv->in_params.fmt.addexp; + else + ctx_priv->st1_addexp -= ctx_priv->in_params.fmt.addexp; + } + } + + ctx_priv->in_filled_sample += (ctx_priv->st1_num_taps / 2) * ctx_priv->st1_num_exp + + ctx_priv->st2_num_taps / 2; + ctx_priv->out_missed_sample = ctx_priv->in_filled_sample * out_s_rate / in_s_rate; + + if (ctx_priv->in_filled_sample * out_s_rate % in_s_rate != 0) + ctx_priv->out_missed_sample += 1; + /* + * To modify the value of a prefilter coefficient, the user must + * perform a write to the register ASRC_PRE_COEFF_FIFOn[COEFF_DATA] + * while the respective context RUN_EN bit is set to 0b0 + */ + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx_id), + EASRC_CC_EN_MASK, 0); + + if (ctx_priv->st1_num_taps > EASRC_MAX_PF_TAPS) { + dev_err(dev, "ST1 taps [%d] mus be lower than %d\n", + ctx_priv->st1_num_taps, EASRC_MAX_PF_TAPS); + ret = -EINVAL; + goto ctx_error; + } + + /* Update ctx ST1_NUM_TAPS in Context Control Extended 2 register */ + regmap_update_bits(easrc->regmap, REG_EASRC_CCE2(ctx_id), + EASRC_CCE2_ST1_TAPS_MASK, + EASRC_CCE2_ST1_TAPS(ctx_priv->st1_num_taps - 1)); + + /* Prefilter Coefficient Write Select to write in ST1 coeff */ + regmap_update_bits(easrc->regmap, REG_EASRC_CCE1(ctx_id), + EASRC_CCE1_COEF_WS_MASK, + EASRC_PF_ST1_COEFF_WR << EASRC_CCE1_COEF_WS_SHIFT); + + ret = fsl_easrc_write_pf_coeff_mem(easrc, ctx_id, + ctx_priv->st1_coeff, + ctx_priv->st1_num_taps, + ctx_priv->st1_addexp); + if (ret) + goto ctx_error; + + if (ctx_priv->st2_num_taps > 0) { + if (ctx_priv->st2_num_taps + ctx_priv->st1_num_taps > EASRC_MAX_PF_TAPS) { + dev_err(dev, "ST2 taps [%d] mus be lower than %d\n", + ctx_priv->st2_num_taps, EASRC_MAX_PF_TAPS); + ret = -EINVAL; + goto ctx_error; + } + + regmap_update_bits(easrc->regmap, REG_EASRC_CCE1(ctx_id), + EASRC_CCE1_PF_TSEN_MASK, + EASRC_CCE1_PF_TSEN); + /* + * Enable prefilter stage1 writeback floating point + * which is used for FLOAT_LE case + */ + regmap_update_bits(easrc->regmap, REG_EASRC_CCE1(ctx_id), + EASRC_CCE1_PF_ST1_WBFP_MASK, + EASRC_CCE1_PF_ST1_WBFP); + + regmap_update_bits(easrc->regmap, REG_EASRC_CCE1(ctx_id), + EASRC_CCE1_PF_EXP_MASK, + EASRC_CCE1_PF_EXP(ctx_priv->st1_num_exp - 1)); + + /* Update ctx ST2_NUM_TAPS in Context Control Extended 2 reg */ + regmap_update_bits(easrc->regmap, REG_EASRC_CCE2(ctx_id), + EASRC_CCE2_ST2_TAPS_MASK, + EASRC_CCE2_ST2_TAPS(ctx_priv->st2_num_taps - 1)); + + /* Prefilter Coefficient Write Select to write in ST2 coeff */ + regmap_update_bits(easrc->regmap, REG_EASRC_CCE1(ctx_id), + EASRC_CCE1_COEF_WS_MASK, + EASRC_PF_ST2_COEFF_WR << EASRC_CCE1_COEF_WS_SHIFT); + + ret = fsl_easrc_write_pf_coeff_mem(easrc, ctx_id, + ctx_priv->st2_coeff, + ctx_priv->st2_num_taps, + ctx_priv->st2_addexp); + if (ret) + goto ctx_error; + } + + return 0; + +ctx_error: + return ret; +} + +static int fsl_easrc_max_ch_for_slot(struct fsl_asrc_pair *ctx, + struct fsl_easrc_slot *slot) +{ + struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; + int st1_mem_alloc = 0, st2_mem_alloc = 0; + int pf_mem_alloc = 0; + int max_channels = 8 - slot->num_channel; + int channels = 0; + + if (ctx_priv->st1_num_taps > 0) { + if (ctx_priv->st2_num_taps > 0) + st1_mem_alloc = + (ctx_priv->st1_num_taps - 1) * ctx_priv->st1_num_exp + 1; + else + st1_mem_alloc = ctx_priv->st1_num_taps; + } + + if (ctx_priv->st2_num_taps > 0) + st2_mem_alloc = ctx_priv->st2_num_taps; + + pf_mem_alloc = st1_mem_alloc + st2_mem_alloc; + + if (pf_mem_alloc != 0) + channels = (6144 - slot->pf_mem_used) / pf_mem_alloc; + else + channels = 8; + + if (channels < max_channels) + max_channels = channels; + + return max_channels; +} + +static int fsl_easrc_config_one_slot(struct fsl_asrc_pair *ctx, + struct fsl_easrc_slot *slot, + unsigned int slot_ctx_idx, + unsigned int *req_channels, + unsigned int *start_channel, + unsigned int *avail_channel) +{ + struct fsl_asrc *easrc = ctx->asrc; + struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; + int st1_chanxexp, st1_mem_alloc = 0, st2_mem_alloc = 0; + unsigned int reg0, reg1, reg2, reg3; + unsigned int addr; + + if (slot->slot_index == 0) { + reg0 = REG_EASRC_DPCS0R0(slot_ctx_idx); + reg1 = REG_EASRC_DPCS0R1(slot_ctx_idx); + reg2 = REG_EASRC_DPCS0R2(slot_ctx_idx); + reg3 = REG_EASRC_DPCS0R3(slot_ctx_idx); + } else { + reg0 = REG_EASRC_DPCS1R0(slot_ctx_idx); + reg1 = REG_EASRC_DPCS1R1(slot_ctx_idx); + reg2 = REG_EASRC_DPCS1R2(slot_ctx_idx); + reg3 = REG_EASRC_DPCS1R3(slot_ctx_idx); + } + + if (*req_channels <= *avail_channel) { + slot->num_channel = *req_channels; + *req_channels = 0; + } else { + slot->num_channel = *avail_channel; + *req_channels -= *avail_channel; + } + + slot->min_channel = *start_channel; + slot->max_channel = *start_channel + slot->num_channel - 1; + slot->ctx_index = ctx->index; + slot->busy = true; + *start_channel += slot->num_channel; + + regmap_update_bits(easrc->regmap, reg0, + EASRC_DPCS0R0_MAXCH_MASK, + EASRC_DPCS0R0_MAXCH(slot->max_channel)); + + regmap_update_bits(easrc->regmap, reg0, + EASRC_DPCS0R0_MINCH_MASK, + EASRC_DPCS0R0_MINCH(slot->min_channel)); + + regmap_update_bits(easrc->regmap, reg0, + EASRC_DPCS0R0_NUMCH_MASK, + EASRC_DPCS0R0_NUMCH(slot->num_channel - 1)); + + regmap_update_bits(easrc->regmap, reg0, + EASRC_DPCS0R0_CTXNUM_MASK, + EASRC_DPCS0R0_CTXNUM(slot->ctx_index)); + + if (ctx_priv->st1_num_taps > 0) { + if (ctx_priv->st2_num_taps > 0) + st1_mem_alloc = + (ctx_priv->st1_num_taps - 1) * slot->num_channel * + ctx_priv->st1_num_exp + slot->num_channel; + else + st1_mem_alloc = ctx_priv->st1_num_taps * slot->num_channel; + + slot->pf_mem_used = st1_mem_alloc; + regmap_update_bits(easrc->regmap, reg2, + EASRC_DPCS0R2_ST1_MA_MASK, + EASRC_DPCS0R2_ST1_MA(st1_mem_alloc)); + + if (slot->slot_index == 1) + addr = PREFILTER_MEM_LEN - st1_mem_alloc; + else + addr = 0; + + regmap_update_bits(easrc->regmap, reg2, + EASRC_DPCS0R2_ST1_SA_MASK, + EASRC_DPCS0R2_ST1_SA(addr)); + } + + if (ctx_priv->st2_num_taps > 0) { + st1_chanxexp = slot->num_channel * (ctx_priv->st1_num_exp - 1); + + regmap_update_bits(easrc->regmap, reg1, + EASRC_DPCS0R1_ST1_EXP_MASK, + EASRC_DPCS0R1_ST1_EXP(st1_chanxexp)); + + st2_mem_alloc = slot->num_channel * ctx_priv->st2_num_taps; + slot->pf_mem_used += st2_mem_alloc; + regmap_update_bits(easrc->regmap, reg3, + EASRC_DPCS0R3_ST2_MA_MASK, + EASRC_DPCS0R3_ST2_MA(st2_mem_alloc)); + + if (slot->slot_index == 1) + addr = PREFILTER_MEM_LEN - st1_mem_alloc - st2_mem_alloc; + else + addr = st1_mem_alloc; + + regmap_update_bits(easrc->regmap, reg3, + EASRC_DPCS0R3_ST2_SA_MASK, + EASRC_DPCS0R3_ST2_SA(addr)); + } + + regmap_update_bits(easrc->regmap, reg0, + EASRC_DPCS0R0_EN_MASK, EASRC_DPCS0R0_EN); + + return 0; +} + +/* + * fsl_easrc_config_slot + * + * A single context can be split amongst any of the 4 context processing pipes + * in the design. + * The total number of channels consumed within the context processor must be + * less than or equal to 8. if a single context is configured to contain more + * than 8 channels then it must be distributed across multiple context + * processing pipe slots. + * + */ +static int fsl_easrc_config_slot(struct fsl_asrc *easrc, unsigned int ctx_id) +{ + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct fsl_asrc_pair *ctx = easrc->pair[ctx_id]; + int req_channels = ctx->channels; + int start_channel = 0, avail_channel; + struct fsl_easrc_slot *slot0, *slot1; + struct fsl_easrc_slot *slota, *slotb; + int i, ret; + + if (req_channels <= 0) + return -EINVAL; + + for (i = 0; i < EASRC_CTX_MAX_NUM; i++) { + slot0 = &easrc_priv->slot[i][0]; + slot1 = &easrc_priv->slot[i][1]; + + if (slot0->busy && slot1->busy) { + continue; + } else if ((slot0->busy && slot0->ctx_index == ctx->index) || + (slot1->busy && slot1->ctx_index == ctx->index)) { + continue; + } else if (!slot0->busy) { + slota = slot0; + slotb = slot1; + slota->slot_index = 0; + } else if (!slot1->busy) { + slota = slot1; + slotb = slot0; + slota->slot_index = 1; + } + + if (!slota || !slotb) + continue; + + avail_channel = fsl_easrc_max_ch_for_slot(ctx, slotb); + if (avail_channel <= 0) + continue; + + ret = fsl_easrc_config_one_slot(ctx, slota, i, &req_channels, + &start_channel, &avail_channel); + if (ret) + return ret; + + if (req_channels > 0) + continue; + else + break; + } + + if (req_channels > 0) { + dev_err(&easrc->pdev->dev, "no avail slot.\n"); + return -EINVAL; + } + + return 0; +} + +/* + * fsl_easrc_release_slot + * + * Clear the slot configuration + */ +static int fsl_easrc_release_slot(struct fsl_asrc *easrc, unsigned int ctx_id) +{ + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct fsl_asrc_pair *ctx = easrc->pair[ctx_id]; + int i; + + for (i = 0; i < EASRC_CTX_MAX_NUM; i++) { + if (easrc_priv->slot[i][0].busy && + easrc_priv->slot[i][0].ctx_index == ctx->index) { + easrc_priv->slot[i][0].busy = false; + easrc_priv->slot[i][0].num_channel = 0; + easrc_priv->slot[i][0].pf_mem_used = 0; + /* set registers */ + regmap_write(easrc->regmap, REG_EASRC_DPCS0R0(i), 0); + regmap_write(easrc->regmap, REG_EASRC_DPCS0R1(i), 0); + regmap_write(easrc->regmap, REG_EASRC_DPCS0R2(i), 0); + regmap_write(easrc->regmap, REG_EASRC_DPCS0R3(i), 0); + } + + if (easrc_priv->slot[i][1].busy && + easrc_priv->slot[i][1].ctx_index == ctx->index) { + easrc_priv->slot[i][1].busy = false; + easrc_priv->slot[i][1].num_channel = 0; + easrc_priv->slot[i][1].pf_mem_used = 0; + /* set registers */ + regmap_write(easrc->regmap, REG_EASRC_DPCS1R0(i), 0); + regmap_write(easrc->regmap, REG_EASRC_DPCS1R1(i), 0); + regmap_write(easrc->regmap, REG_EASRC_DPCS1R2(i), 0); + regmap_write(easrc->regmap, REG_EASRC_DPCS1R3(i), 0); + } + } + + return 0; +} + +/* + * fsl_easrc_config_context + * + * Configure the register relate with context. + */ +int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id) +{ + struct fsl_easrc_ctx_priv *ctx_priv; + struct fsl_asrc_pair *ctx; + struct device *dev; + unsigned long lock_flags; + int ret; + + if (!easrc) + return -ENODEV; + + dev = &easrc->pdev->dev; + + if (ctx_id >= EASRC_CTX_MAX_NUM) { + dev_err(dev, "Invalid context id[%d]\n", ctx_id); + return -EINVAL; + } + + ctx = easrc->pair[ctx_id]; + + ctx_priv = ctx->private; + + fsl_easrc_normalize_rates(ctx); + + ret = fsl_easrc_set_rs_ratio(ctx); + if (ret) + return ret; + + /* Initialize the context coeficients */ + ret = fsl_easrc_prefilter_config(easrc, ctx->index); + if (ret) + return ret; + + spin_lock_irqsave(&easrc->lock, lock_flags); + ret = fsl_easrc_config_slot(easrc, ctx->index); + spin_unlock_irqrestore(&easrc->lock, lock_flags); + if (ret) + return ret; + + /* + * Both prefilter and resampling filters can use following + * initialization modes: + * 2 - zero-fil mode + * 1 - replication mode + * 0 - software control + */ + regmap_update_bits(easrc->regmap, REG_EASRC_CCE1(ctx_id), + EASRC_CCE1_RS_INIT_MASK, + EASRC_CCE1_RS_INIT(ctx_priv->rs_init_mode)); + + regmap_update_bits(easrc->regmap, REG_EASRC_CCE1(ctx_id), + EASRC_CCE1_PF_INIT_MASK, + EASRC_CCE1_PF_INIT(ctx_priv->pf_init_mode)); + + /* + * Context Input FIFO Watermark + * DMA request is generated when input FIFO < FIFO_WTMK + */ + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx_id), + EASRC_CC_FIFO_WTMK_MASK, + EASRC_CC_FIFO_WTMK(ctx_priv->in_params.fifo_wtmk)); + + /* + * Context Output FIFO Watermark + * DMA request is generated when output FIFO > FIFO_WTMK + * So we set fifo_wtmk -1 to register. + */ + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx_id), + EASRC_COC_FIFO_WTMK_MASK, + EASRC_COC_FIFO_WTMK(ctx_priv->out_params.fifo_wtmk - 1)); + + /* Number of channels */ + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx_id), + EASRC_CC_CHEN_MASK, + EASRC_CC_CHEN(ctx->channels - 1)); + return 0; +} + +static int fsl_easrc_process_format(struct fsl_asrc_pair *ctx, + struct fsl_easrc_data_fmt *fmt, + snd_pcm_format_t raw_fmt) +{ + struct fsl_asrc *easrc = ctx->asrc; + struct fsl_easrc_priv *easrc_priv = easrc->private; + int ret; + + if (!fmt) + return -EINVAL; + + /* + * Context Input Floating Point Format + * 0 - Integer Format + * 1 - Single Precision FP Format + */ + fmt->floating_point = !snd_pcm_format_linear(raw_fmt); + fmt->sample_pos = 0; + fmt->iec958 = 0; + + /* Get the data width */ + switch (snd_pcm_format_width(raw_fmt)) { + case 16: + fmt->width = EASRC_WIDTH_16_BIT; + fmt->addexp = 15; + break; + case 20: + fmt->width = EASRC_WIDTH_20_BIT; + fmt->addexp = 19; + break; + case 24: + fmt->width = EASRC_WIDTH_24_BIT; + fmt->addexp = 23; + break; + case 32: + fmt->width = EASRC_WIDTH_32_BIT; + fmt->addexp = 31; + break; + default: + return -EINVAL; + } + + switch (raw_fmt) { + case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: + fmt->width = easrc_priv->bps_iec958[ctx->index]; + fmt->iec958 = 1; + fmt->floating_point = 0; + if (fmt->width == EASRC_WIDTH_16_BIT) { + fmt->sample_pos = 12; + fmt->addexp = 15; + } else if (fmt->width == EASRC_WIDTH_20_BIT) { + fmt->sample_pos = 8; + fmt->addexp = 19; + } else if (fmt->width == EASRC_WIDTH_24_BIT) { + fmt->sample_pos = 4; + fmt->addexp = 23; + } + break; + default: + break; + } + + /* + * Data Endianness + * 0 - Little-Endian + * 1 - Big-Endian + */ + ret = snd_pcm_format_big_endian(raw_fmt); + if (ret < 0) + return ret; + + fmt->endianness = ret; + + /* + * Input Data sign + * 0b - Signed Format + * 1b - Unsigned Format + */ + fmt->unsign = snd_pcm_format_unsigned(raw_fmt) > 0 ? 1 : 0; + + return 0; +} + +int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx, + snd_pcm_format_t *in_raw_format, + snd_pcm_format_t *out_raw_format) +{ + struct fsl_asrc *easrc = ctx->asrc; + struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; + struct fsl_easrc_data_fmt *in_fmt = &ctx_priv->in_params.fmt; + struct fsl_easrc_data_fmt *out_fmt = &ctx_priv->out_params.fmt; + int ret; + + /* Get the bitfield values for input data format */ + if (in_raw_format && out_raw_format) { + ret = fsl_easrc_process_format(ctx, in_fmt, *in_raw_format); + if (ret) + return ret; + } + + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_BPS_MASK, + EASRC_CC_BPS(in_fmt->width)); + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_ENDIANNESS_MASK, + in_fmt->endianness << EASRC_CC_ENDIANNESS_SHIFT); + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_FMT_MASK, + in_fmt->floating_point << EASRC_CC_FMT_SHIFT); + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_INSIGN_MASK, + in_fmt->unsign << EASRC_CC_INSIGN_SHIFT); + + /* In Sample Position */ + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_SAMPLE_POS_MASK, + EASRC_CC_SAMPLE_POS(in_fmt->sample_pos)); + + /* Get the bitfield values for input data format */ + if (in_raw_format && out_raw_format) { + ret = fsl_easrc_process_format(ctx, out_fmt, *out_raw_format); + if (ret) + return ret; + } + + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx->index), + EASRC_COC_BPS_MASK, + EASRC_COC_BPS(out_fmt->width)); + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx->index), + EASRC_COC_ENDIANNESS_MASK, + out_fmt->endianness << EASRC_COC_ENDIANNESS_SHIFT); + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx->index), + EASRC_COC_FMT_MASK, + out_fmt->floating_point << EASRC_COC_FMT_SHIFT); + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx->index), + EASRC_COC_OUTSIGN_MASK, + out_fmt->unsign << EASRC_COC_OUTSIGN_SHIFT); + + /* Out Sample Position */ + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx->index), + EASRC_COC_SAMPLE_POS_MASK, + EASRC_COC_SAMPLE_POS(out_fmt->sample_pos)); + + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx->index), + EASRC_COC_IEC_EN_MASK, + out_fmt->iec958 << EASRC_COC_IEC_EN_SHIFT); + + return ret; +} + +/* + * The ASRC provides interleaving support in hardware to ensure that a + * variety of sample sources can be internally combined + * to conform with this format. Interleaving parameters are accessed + * through the ASRC_CTRL_IN_ACCESSa and ASRC_CTRL_OUT_ACCESSa registers + */ +int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) +{ + struct fsl_easrc_ctx_priv *ctx_priv; + struct device *dev; + struct fsl_asrc *easrc; + + if (!ctx) + return -ENODEV; + + easrc = ctx->asrc; + ctx_priv = ctx->private; + dev = &easrc->pdev->dev; + + /* input interleaving parameters */ + regmap_update_bits(easrc->regmap, REG_EASRC_CIA(ctx->index), + EASRC_CIA_ITER_MASK, + EASRC_CIA_ITER(ctx_priv->in_params.iterations)); + regmap_update_bits(easrc->regmap, REG_EASRC_CIA(ctx->index), + EASRC_CIA_GRLEN_MASK, + EASRC_CIA_GRLEN(ctx_priv->in_params.group_len)); + regmap_update_bits(easrc->regmap, REG_EASRC_CIA(ctx->index), + EASRC_CIA_ACCLEN_MASK, + EASRC_CIA_ACCLEN(ctx_priv->in_params.access_len)); + + /* output interleaving parameters */ + regmap_update_bits(easrc->regmap, REG_EASRC_COA(ctx->index), + EASRC_COA_ITER_MASK, + EASRC_COA_ITER(ctx_priv->out_params.iterations)); + regmap_update_bits(easrc->regmap, REG_EASRC_COA(ctx->index), + EASRC_COA_GRLEN_MASK, + EASRC_COA_GRLEN(ctx_priv->out_params.group_len)); + regmap_update_bits(easrc->regmap, REG_EASRC_COA(ctx->index), + EASRC_COA_ACCLEN_MASK, + EASRC_COA_ACCLEN(ctx_priv->out_params.access_len)); + + return 0; +} + +/* + * Request one of the available contexts + * + * Returns a negative number on error and >=0 as context id + * on success + */ +int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx) +{ + enum asrc_pair_index index = ASRC_INVALID_PAIR; + struct fsl_asrc *easrc = ctx->asrc; + struct device *dev; + unsigned long lock_flags; + int ret = 0; + int i; + + dev = &easrc->pdev->dev; + + spin_lock_irqsave(&easrc->lock, lock_flags); + + for (i = ASRC_PAIR_A; i < EASRC_CTX_MAX_NUM; i++) { + if (easrc->pair[i]) + continue; + + index = i; + break; + } + + if (index == ASRC_INVALID_PAIR) { + dev_err(dev, "all contexts are busy\n"); + ret = -EBUSY; + } else if (channels > easrc->channel_avail) { + dev_err(dev, "can't give the required channels: %d\n", + channels); + ret = -EINVAL; + } else { + ctx->index = index; + ctx->channels = channels; + easrc->pair[index] = ctx; + easrc->channel_avail -= channels; + } + + spin_unlock_irqrestore(&easrc->lock, lock_flags); + + return ret; +} + +/* + * Release the context + * + * This funciton is mainly doing the revert thing in request context + */ +void fsl_easrc_release_context(struct fsl_asrc_pair *ctx) +{ + unsigned long lock_flags; + struct fsl_asrc *easrc; + struct device *dev; + + if (!ctx) + return; + + easrc = ctx->asrc; + dev = &easrc->pdev->dev; + + spin_lock_irqsave(&easrc->lock, lock_flags); + + fsl_easrc_release_slot(easrc, ctx->index); + + easrc->channel_avail += ctx->channels; + easrc->pair[ctx->index] = NULL; + + spin_unlock_irqrestore(&easrc->lock, lock_flags); +} + +/* + * Start the context + * + * Enable the DMA request and context + */ +int fsl_easrc_start_context(struct fsl_asrc_pair *ctx) +{ + struct fsl_asrc *easrc = ctx->asrc; + + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_FWMDE_MASK, EASRC_CC_FWMDE); + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx->index), + EASRC_COC_FWMDE_MASK, EASRC_COC_FWMDE); + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_EN_MASK, EASRC_CC_EN); + return 0; +} + +/* + * Stop the context + * + * Disable the DMA request and context + */ +int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) +{ + struct fsl_asrc *easrc = ctx->asrc; + int val, i; + int size = 0; + int retry = 200; + + regmap_read(easrc->regmap, REG_EASRC_CC(ctx->index), &val); + + if (val & EASRC_CC_EN_MASK) { + regmap_update_bits(easrc->regmap, + REG_EASRC_CC(ctx->index), + EASRC_CC_STOP_MASK, EASRC_CC_STOP); + do { + regmap_read(easrc->regmap, REG_EASRC_SFS(ctx->index), &val); + val &= EASRC_SFS_NSGO_MASK; + size = val >> EASRC_SFS_NSGO_SHIFT; + + /* Read FIFO, drop the data */ + for (i = 0; i < size * ctx->channels; i++) + regmap_read(easrc->regmap, REG_EASRC_RDFIFO(ctx->index), &val); + /* Check RUN_STOP_DONE */ + regmap_read(easrc->regmap, REG_EASRC_IRQF, &val); + if (val & EASRC_IRQF_RSD(1 << ctx->index)) { + /*Clear RUN_STOP_DONE*/ + regmap_write_bits(easrc->regmap, + REG_EASRC_IRQF, + EASRC_IRQF_RSD(1 << ctx->index), + EASRC_IRQF_RSD(1 << ctx->index)); + break; + } + udelay(100); + } while (--retry); + + if (retry == 0) + dev_warn(&easrc->pdev->dev, "RUN STOP fail\n"); + } + + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_EN_MASK | EASRC_CC_STOP_MASK, 0); + regmap_update_bits(easrc->regmap, REG_EASRC_CC(ctx->index), + EASRC_CC_FWMDE_MASK, 0); + regmap_update_bits(easrc->regmap, REG_EASRC_COC(ctx->index), + EASRC_COC_FWMDE_MASK, 0); + return 0; +} + +struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx, + bool dir) +{ + struct fsl_asrc *easrc = ctx->asrc; + enum asrc_pair_index index = ctx->index; + char name[8]; + + /* Example of dma name: ctx0_rx */ + sprintf(name, "ctx%c_%cx", index + '0', dir == IN ? 'r' : 't'); + + return dma_request_slave_channel(&easrc->pdev->dev, name); +}; +EXPORT_SYMBOL_GPL(fsl_easrc_get_dma_channel); + +static const unsigned int easrc_rates[] = { + 8000, 11025, 12000, 16000, + 22050, 24000, 32000, 44100, + 48000, 64000, 88200, 96000, + 128000, 176400, 192000, 256000, + 352800, 384000, 705600, 768000, +}; + +static const struct snd_pcm_hw_constraint_list easrc_rate_constraints = { + .count = ARRAY_SIZE(easrc_rates), + .list = easrc_rates, +}; + +static int fsl_easrc_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &easrc_rate_constraints); +} + +static int fsl_easrc_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct fsl_asrc_pair *ctx = runtime->private_data; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = fsl_easrc_start_context(ctx); + if (ret) + return ret; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = fsl_easrc_stop_context(ctx); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int fsl_easrc_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct fsl_asrc *easrc = snd_soc_dai_get_drvdata(dai); + struct snd_pcm_runtime *runtime = substream->runtime; + struct device *dev = &easrc->pdev->dev; + struct fsl_asrc_pair *ctx = runtime->private_data; + struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; + unsigned int channels = params_channels(params); + unsigned int rate = params_rate(params); + snd_pcm_format_t format = params_format(params); + int ret; + + ret = fsl_easrc_request_context(channels, ctx); + if (ret) { + dev_err(dev, "failed to request context\n"); + return ret; + } + + ctx_priv->ctx_streams |= BIT(substream->stream); + + /* + * Set the input and output ratio so we can compute + * the resampling ratio in RS_LOW/HIGH + */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ctx_priv->in_params.sample_rate = rate; + ctx_priv->in_params.sample_format = format; + ctx_priv->out_params.sample_rate = easrc->asrc_rate; + ctx_priv->out_params.sample_format = easrc->asrc_format; + } else { + ctx_priv->out_params.sample_rate = rate; + ctx_priv->out_params.sample_format = format; + ctx_priv->in_params.sample_rate = easrc->asrc_rate; + ctx_priv->in_params.sample_format = easrc->asrc_format; + } + + ctx->channels = channels; + ctx_priv->in_params.fifo_wtmk = 0x20; + ctx_priv->out_params.fifo_wtmk = 0x20; + + /* + * Do only rate conversion and keep the same format for input + * and output data + */ + ret = fsl_easrc_set_ctx_format(ctx, + &ctx_priv->in_params.sample_format, + &ctx_priv->out_params.sample_format); + if (ret) { + dev_err(dev, "failed to set format %d", ret); + return ret; + } + + ret = fsl_easrc_config_context(easrc, ctx->index); + if (ret) { + dev_err(dev, "failed to config context\n"); + return ret; + } + + ctx_priv->in_params.iterations = 1; + ctx_priv->in_params.group_len = ctx->channels; + ctx_priv->in_params.access_len = ctx->channels; + ctx_priv->out_params.iterations = 1; + ctx_priv->out_params.group_len = ctx->channels; + ctx_priv->out_params.access_len = ctx->channels; + + ret = fsl_easrc_set_ctx_organziation(ctx); + if (ret) { + dev_err(dev, "failed to set fifo organization\n"); + return ret; + } + + return 0; +} + +static int fsl_easrc_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct fsl_asrc_pair *ctx = runtime->private_data; + struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; + + if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) { + ctx_priv->ctx_streams &= ~BIT(substream->stream); + fsl_easrc_release_context(ctx); + } + + return 0; +} + +static struct snd_soc_dai_ops fsl_easrc_dai_ops = { + .startup = fsl_easrc_startup, + .trigger = fsl_easrc_trigger, + .hw_params = fsl_easrc_hw_params, + .hw_free = fsl_easrc_hw_free, +}; + +static int fsl_easrc_dai_probe(struct snd_soc_dai *cpu_dai) +{ + struct fsl_asrc *easrc = dev_get_drvdata(cpu_dai->dev); + + snd_soc_dai_init_dma_data(cpu_dai, + &easrc->dma_params_tx, + &easrc->dma_params_rx); + return 0; +} + +static struct snd_soc_dai_driver fsl_easrc_dai = { + .probe = fsl_easrc_dai_probe, + .playback = { + .stream_name = "ASRC-Playback", + .channels_min = 1, + .channels_max = 32, + .rate_min = 8000, + .rate_max = 768000, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = FSL_EASRC_FORMATS, + }, + .capture = { + .stream_name = "ASRC-Capture", + .channels_min = 1, + .channels_max = 32, + .rate_min = 8000, + .rate_max = 768000, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = FSL_EASRC_FORMATS | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, + }, + .ops = &fsl_easrc_dai_ops, +}; + +static const struct snd_soc_component_driver fsl_easrc_component = { + .name = "fsl-easrc-dai", + .controls = fsl_easrc_snd_controls, + .num_controls = ARRAY_SIZE(fsl_easrc_snd_controls), +}; + +static const struct reg_default fsl_easrc_reg_defaults[] = { + {REG_EASRC_WRFIFO(0), 0x00000000}, + {REG_EASRC_WRFIFO(1), 0x00000000}, + {REG_EASRC_WRFIFO(2), 0x00000000}, + {REG_EASRC_WRFIFO(3), 0x00000000}, + {REG_EASRC_RDFIFO(0), 0x00000000}, + {REG_EASRC_RDFIFO(1), 0x00000000}, + {REG_EASRC_RDFIFO(2), 0x00000000}, + {REG_EASRC_RDFIFO(3), 0x00000000}, + {REG_EASRC_CC(0), 0x00000000}, + {REG_EASRC_CC(1), 0x00000000}, + {REG_EASRC_CC(2), 0x00000000}, + {REG_EASRC_CC(3), 0x00000000}, + {REG_EASRC_CCE1(0), 0x00000000}, + {REG_EASRC_CCE1(1), 0x00000000}, + {REG_EASRC_CCE1(2), 0x00000000}, + {REG_EASRC_CCE1(3), 0x00000000}, + {REG_EASRC_CCE2(0), 0x00000000}, + {REG_EASRC_CCE2(1), 0x00000000}, + {REG_EASRC_CCE2(2), 0x00000000}, + {REG_EASRC_CCE2(3), 0x00000000}, + {REG_EASRC_CIA(0), 0x00000000}, + {REG_EASRC_CIA(1), 0x00000000}, + {REG_EASRC_CIA(2), 0x00000000}, + {REG_EASRC_CIA(3), 0x00000000}, + {REG_EASRC_DPCS0R0(0), 0x00000000}, + {REG_EASRC_DPCS0R0(1), 0x00000000}, + {REG_EASRC_DPCS0R0(2), 0x00000000}, + {REG_EASRC_DPCS0R0(3), 0x00000000}, + {REG_EASRC_DPCS0R1(0), 0x00000000}, + {REG_EASRC_DPCS0R1(1), 0x00000000}, + {REG_EASRC_DPCS0R1(2), 0x00000000}, + {REG_EASRC_DPCS0R1(3), 0x00000000}, + {REG_EASRC_DPCS0R2(0), 0x00000000}, + {REG_EASRC_DPCS0R2(1), 0x00000000}, + {REG_EASRC_DPCS0R2(2), 0x00000000}, + {REG_EASRC_DPCS0R2(3), 0x00000000}, + {REG_EASRC_DPCS0R3(0), 0x00000000}, + {REG_EASRC_DPCS0R3(1), 0x00000000}, + {REG_EASRC_DPCS0R3(2), 0x00000000}, + {REG_EASRC_DPCS0R3(3), 0x00000000}, + {REG_EASRC_DPCS1R0(0), 0x00000000}, + {REG_EASRC_DPCS1R0(1), 0x00000000}, + {REG_EASRC_DPCS1R0(2), 0x00000000}, + {REG_EASRC_DPCS1R0(3), 0x00000000}, + {REG_EASRC_DPCS1R1(0), 0x00000000}, + {REG_EASRC_DPCS1R1(1), 0x00000000}, + {REG_EASRC_DPCS1R1(2), 0x00000000}, + {REG_EASRC_DPCS1R1(3), 0x00000000}, + {REG_EASRC_DPCS1R2(0), 0x00000000}, + {REG_EASRC_DPCS1R2(1), 0x00000000}, + {REG_EASRC_DPCS1R2(2), 0x00000000}, + {REG_EASRC_DPCS1R2(3), 0x00000000}, + {REG_EASRC_DPCS1R3(0), 0x00000000}, + {REG_EASRC_DPCS1R3(1), 0x00000000}, + {REG_EASRC_DPCS1R3(2), 0x00000000}, + {REG_EASRC_DPCS1R3(3), 0x00000000}, + {REG_EASRC_COC(0), 0x00000000}, + {REG_EASRC_COC(1), 0x00000000}, + {REG_EASRC_COC(2), 0x00000000}, + {REG_EASRC_COC(3), 0x00000000}, + {REG_EASRC_COA(0), 0x00000000}, + {REG_EASRC_COA(1), 0x00000000}, + {REG_EASRC_COA(2), 0x00000000}, + {REG_EASRC_COA(3), 0x00000000}, + {REG_EASRC_SFS(0), 0x00000000}, + {REG_EASRC_SFS(1), 0x00000000}, + {REG_EASRC_SFS(2), 0x00000000}, + {REG_EASRC_SFS(3), 0x00000000}, + {REG_EASRC_RRL(0), 0x00000000}, + {REG_EASRC_RRL(1), 0x00000000}, + {REG_EASRC_RRL(2), 0x00000000}, + {REG_EASRC_RRL(3), 0x00000000}, + {REG_EASRC_RRH(0), 0x00000000}, + {REG_EASRC_RRH(1), 0x00000000}, + {REG_EASRC_RRH(2), 0x00000000}, + {REG_EASRC_RRH(3), 0x00000000}, + {REG_EASRC_RUC(0), 0x00000000}, + {REG_EASRC_RUC(1), 0x00000000}, + {REG_EASRC_RUC(2), 0x00000000}, + {REG_EASRC_RUC(3), 0x00000000}, + {REG_EASRC_RUR(0), 0x7FFFFFFF}, + {REG_EASRC_RUR(1), 0x7FFFFFFF}, + {REG_EASRC_RUR(2), 0x7FFFFFFF}, + {REG_EASRC_RUR(3), 0x7FFFFFFF}, + {REG_EASRC_RCTCL, 0x00000000}, + {REG_EASRC_RCTCH, 0x00000000}, + {REG_EASRC_PCF(0), 0x00000000}, + {REG_EASRC_PCF(1), 0x00000000}, + {REG_EASRC_PCF(2), 0x00000000}, + {REG_EASRC_PCF(3), 0x00000000}, + {REG_EASRC_CRCM, 0x00000000}, + {REG_EASRC_CRCC, 0x00000000}, + {REG_EASRC_IRQC, 0x00000FFF}, + {REG_EASRC_IRQF, 0x00000000}, + {REG_EASRC_CS0(0), 0x00000000}, + {REG_EASRC_CS0(1), 0x00000000}, + {REG_EASRC_CS0(2), 0x00000000}, + {REG_EASRC_CS0(3), 0x00000000}, + {REG_EASRC_CS1(0), 0x00000000}, + {REG_EASRC_CS1(1), 0x00000000}, + {REG_EASRC_CS1(2), 0x00000000}, + {REG_EASRC_CS1(3), 0x00000000}, + {REG_EASRC_CS2(0), 0x00000000}, + {REG_EASRC_CS2(1), 0x00000000}, + {REG_EASRC_CS2(2), 0x00000000}, + {REG_EASRC_CS2(3), 0x00000000}, + {REG_EASRC_CS3(0), 0x00000000}, + {REG_EASRC_CS3(1), 0x00000000}, + {REG_EASRC_CS3(2), 0x00000000}, + {REG_EASRC_CS3(3), 0x00000000}, + {REG_EASRC_CS4(0), 0x00000000}, + {REG_EASRC_CS4(1), 0x00000000}, + {REG_EASRC_CS4(2), 0x00000000}, + {REG_EASRC_CS4(3), 0x00000000}, + {REG_EASRC_CS5(0), 0x00000000}, + {REG_EASRC_CS5(1), 0x00000000}, + {REG_EASRC_CS5(2), 0x00000000}, + {REG_EASRC_CS5(3), 0x00000000}, + {REG_EASRC_DBGC, 0x00000000}, + {REG_EASRC_DBGS, 0x00000000}, +}; + +static const struct regmap_range fsl_easrc_readable_ranges[] = { + regmap_reg_range(REG_EASRC_RDFIFO(0), REG_EASRC_RCTCH), + regmap_reg_range(REG_EASRC_PCF(0), REG_EASRC_PCF(3)), + regmap_reg_range(REG_EASRC_CRCC, REG_EASRC_DBGS), +}; + +static const struct regmap_access_table fsl_easrc_readable_table = { + .yes_ranges = fsl_easrc_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(fsl_easrc_readable_ranges), +}; + +static const struct regmap_range fsl_easrc_writeable_ranges[] = { + regmap_reg_range(REG_EASRC_WRFIFO(0), REG_EASRC_WRFIFO(3)), + regmap_reg_range(REG_EASRC_CC(0), REG_EASRC_COA(3)), + regmap_reg_range(REG_EASRC_RRL(0), REG_EASRC_RCTCH), + regmap_reg_range(REG_EASRC_PCF(0), REG_EASRC_DBGC), +}; + +static const struct regmap_access_table fsl_easrc_writeable_table = { + .yes_ranges = fsl_easrc_writeable_ranges, + .n_yes_ranges = ARRAY_SIZE(fsl_easrc_writeable_ranges), +}; + +static const struct regmap_range fsl_easrc_volatileable_ranges[] = { + regmap_reg_range(REG_EASRC_RDFIFO(0), REG_EASRC_RDFIFO(3)), + regmap_reg_range(REG_EASRC_SFS(0), REG_EASRC_SFS(3)), + regmap_reg_range(REG_EASRC_IRQF, REG_EASRC_IRQF), + regmap_reg_range(REG_EASRC_DBGS, REG_EASRC_DBGS), +}; + +static const struct regmap_access_table fsl_easrc_volatileable_table = { + .yes_ranges = fsl_easrc_volatileable_ranges, + .n_yes_ranges = ARRAY_SIZE(fsl_easrc_volatileable_ranges), +}; + +static const struct regmap_config fsl_easrc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + + .max_register = REG_EASRC_DBGS, + .reg_defaults = fsl_easrc_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(fsl_easrc_reg_defaults), + .rd_table = &fsl_easrc_readable_table, + .wr_table = &fsl_easrc_writeable_table, + .volatile_table = &fsl_easrc_volatileable_table, + .cache_type = REGCACHE_RBTREE, +}; + +#ifdef DEBUG +static void fsl_easrc_dump_firmware(struct fsl_asrc *easrc) +{ + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct asrc_firmware_hdr *firm = easrc_priv->firmware_hdr; + struct interp_params *interp = easrc_priv->interp; + struct prefil_params *prefil = easrc_priv->prefil; + struct device *dev = &easrc->pdev->dev; + int i; + + if (firm->magic != FIRMWARE_MAGIC) { + dev_err(dev, "Wrong magic. Something went wrong!"); + return; + } + + dev_dbg(dev, "Firmware v%u dump:\n", firm->firmware_version); + dev_dbg(dev, "Num prefitler scenarios: %u\n", firm->prefil_scen); + dev_dbg(dev, "Num interpolation scenarios: %u\n", firm->interp_scen); + dev_dbg(dev, "\nInterpolation scenarios:\n"); + + for (i = 0; i < firm->interp_scen; i++) { + if (interp[i].magic != FIRMWARE_MAGIC) { + dev_dbg(dev, "%d. wrong interp magic: %x\n", + i, interp[i].magic); + continue; + } + dev_dbg(dev, "%d. taps: %u, phases: %u, center: %llu\n", i, + interp[i].num_taps, interp[i].num_phases, + interp[i].center_tap); + } + + for (i = 0; i < firm->prefil_scen; i++) { + if (prefil[i].magic != FIRMWARE_MAGIC) { + dev_dbg(dev, "%d. wrong prefil magic: %x\n", + i, prefil[i].magic); + continue; + } + dev_dbg(dev, "%d. insr: %u, outsr: %u, st1: %u, st2: %u\n", i, + prefil[i].insr, prefil[i].outsr, + prefil[i].st1_taps, prefil[i].st2_taps); + } + + dev_dbg(dev, "end of firmware dump\n"); +} +#endif + +static int fsl_easrc_get_firmware(struct fsl_asrc *easrc) +{ + struct fsl_easrc_priv *easrc_priv; + const struct firmware **fw_p; + u32 pnum, inum, offset; + const u8 *data; + int ret; + + if (!easrc) + return -EINVAL; + + easrc_priv = easrc->private; + fw_p = &easrc_priv->fw; + + ret = request_firmware(fw_p, easrc_priv->fw_name, &easrc->pdev->dev); + if (ret) + return ret; + + data = easrc_priv->fw->data; + + easrc_priv->firmware_hdr = (struct asrc_firmware_hdr *)data; + pnum = easrc_priv->firmware_hdr->prefil_scen; + inum = easrc_priv->firmware_hdr->interp_scen; + + if (inum) { + offset = sizeof(struct asrc_firmware_hdr); + easrc_priv->interp = (struct interp_params *)(data + offset); + } + + if (pnum) { + offset = sizeof(struct asrc_firmware_hdr) + + inum * sizeof(struct interp_params); + easrc_priv->prefil = (struct prefil_params *)(data + offset); + } + +#ifdef DEBUG + fsl_easrc_dump_firmware(easrc); +#endif + + return 0; +} + +static irqreturn_t fsl_easrc_isr(int irq, void *dev_id) +{ + struct fsl_asrc *easrc = (struct fsl_asrc *)dev_id; + struct device *dev = &easrc->pdev->dev; + int val; + + regmap_read(easrc->regmap, REG_EASRC_IRQF, &val); + + if (val & EASRC_IRQF_OER_MASK) + dev_dbg(dev, "output FIFO underflow\n"); + + if (val & EASRC_IRQF_IFO_MASK) + dev_dbg(dev, "input FIFO overflow\n"); + + return IRQ_HANDLED; +} + +static int fsl_easrc_get_fifo_addr(u8 dir, enum asrc_pair_index index) +{ + return REG_EASRC_FIFO(dir, index); +} + +static const struct of_device_id fsl_easrc_dt_ids[] = { + { .compatible = "fsl,imx8mn-easrc",}, + {} +}; +MODULE_DEVICE_TABLE(of, fsl_easrc_dt_ids); + +static int fsl_easrc_probe(struct platform_device *pdev) +{ + struct fsl_easrc_priv *easrc_priv; + struct device *dev = &pdev->dev; + struct fsl_asrc *easrc; + struct resource *res; + struct device_node *np; + void __iomem *regs; + int ret, irq; + + easrc = devm_kzalloc(dev, sizeof(*easrc), GFP_KERNEL); + if (!easrc) + return -ENOMEM; + + easrc_priv = devm_kzalloc(dev, sizeof(*easrc_priv), GFP_KERNEL); + if (!easrc_priv) + return -ENOMEM; + + easrc->pdev = pdev; + easrc->private = easrc_priv; + np = dev->of_node; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) { + dev_err(&pdev->dev, "failed ioremap\n"); + return PTR_ERR(regs); + } + + easrc->paddr = res->start; + + easrc->regmap = devm_regmap_init_mmio_clk(dev, "mem", regs, + &fsl_easrc_regmap_config); + if (IS_ERR(easrc->regmap)) { + dev_err(dev, "failed to init regmap"); + return PTR_ERR(easrc->regmap); + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "no irq for node %pOF\n", np); + return irq; + } + + ret = devm_request_irq(&pdev->dev, irq, fsl_easrc_isr, 0, + dev_name(dev), easrc); + if (ret) { + dev_err(dev, "failed to claim irq %u: %d\n", irq, ret); + return ret; + } + + easrc->mem_clk = devm_clk_get(dev, "mem"); + if (IS_ERR(easrc->mem_clk)) { + dev_err(dev, "failed to get mem clock\n"); + return PTR_ERR(easrc->mem_clk); + } + + /* Set default value */ + easrc->channel_avail = 32; + easrc->get_dma_channel = fsl_easrc_get_dma_channel; + easrc->request_pair = fsl_easrc_request_context; + easrc->release_pair = fsl_easrc_release_context; + easrc->get_fifo_addr = fsl_easrc_get_fifo_addr; + easrc->pair_priv_size = sizeof(struct fsl_easrc_ctx_priv); + + easrc_priv->rs_num_taps = EASRC_RS_32_TAPS; + easrc_priv->const_coeff = 0x3FF0000000000000; + + ret = of_property_read_u32(np, "fsl,asrc-rate", &easrc->asrc_rate); + if (ret) { + dev_err(dev, "failed to asrc rate\n"); + return ret; + } + + ret = of_property_read_u32(np, "fsl,asrc-format", &easrc->asrc_format); + if (ret) { + dev_err(dev, "failed to asrc format\n"); + return ret; + } + + if (!(FSL_EASRC_FORMATS & (1ULL << easrc->asrc_format))) { + dev_warn(dev, "unsupported format, switching to S24_LE\n"); + easrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE; + } + + ret = of_property_read_string(np, "firmware-name", + &easrc_priv->fw_name); + if (ret) { + dev_err(dev, "failed to get firmware name\n"); + return ret; + } + + platform_set_drvdata(pdev, easrc); + pm_runtime_enable(dev); + + spin_lock_init(&easrc->lock); + + regcache_cache_only(easrc->regmap, true); + + ret = devm_snd_soc_register_component(dev, &fsl_easrc_component, + &fsl_easrc_dai, 1); + if (ret) { + dev_err(dev, "failed to register ASoC DAI\n"); + return ret; + } + + ret = devm_snd_soc_register_component(dev, &fsl_asrc_component, + NULL, 0); + if (ret) { + dev_err(&pdev->dev, "failed to register ASoC platform\n"); + return ret; + } + + return 0; +} + +static int fsl_easrc_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +#ifdef CONFIG_PM +static int fsl_easrc_runtime_suspend(struct device *dev) +{ + struct fsl_asrc *easrc = dev_get_drvdata(dev); + struct fsl_easrc_priv *easrc_priv = easrc->private; + unsigned long lock_flags; + + regcache_cache_only(easrc->regmap, true); + + clk_disable_unprepare(easrc->mem_clk); + + spin_lock_irqsave(&easrc->lock, lock_flags); + easrc_priv->firmware_loaded = 0; + spin_unlock_irqrestore(&easrc->lock, lock_flags); + + return 0; +} + +static int fsl_easrc_runtime_resume(struct device *dev) +{ + struct fsl_asrc *easrc = dev_get_drvdata(dev); + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct fsl_easrc_ctx_priv *ctx_priv; + struct fsl_asrc_pair *ctx; + unsigned long lock_flags; + int ret; + int i; + + ret = clk_prepare_enable(easrc->mem_clk); + if (ret) + return ret; + + regcache_cache_only(easrc->regmap, false); + regcache_mark_dirty(easrc->regmap); + regcache_sync(easrc->regmap); + + spin_lock_irqsave(&easrc->lock, lock_flags); + if (easrc_priv->firmware_loaded) { + spin_unlock_irqrestore(&easrc->lock, lock_flags); + goto skip_load; + } + easrc_priv->firmware_loaded = 1; + spin_unlock_irqrestore(&easrc->lock, lock_flags); + + ret = fsl_easrc_get_firmware(easrc); + if (ret) { + dev_err(dev, "failed to get firmware\n"); + goto disable_mem_clk; + } + + /* + * Write Resampling Coefficients + * The coefficient RAM must be configured prior to beginning of + * any context processing within the ASRC + */ + ret = fsl_easrc_resampler_config(easrc); + if (ret) { + dev_err(dev, "resampler config failed\n"); + goto disable_mem_clk; + } + + for (i = ASRC_PAIR_A; i < EASRC_CTX_MAX_NUM; i++) { + ctx = easrc->pair[i]; + if (!ctx) + continue; + + ctx_priv = ctx->private; + fsl_easrc_set_rs_ratio(ctx); + ctx_priv->out_missed_sample = ctx_priv->in_filled_sample * + ctx_priv->out_params.sample_rate / + ctx_priv->in_params.sample_rate; + if (ctx_priv->in_filled_sample * ctx_priv->out_params.sample_rate + % ctx_priv->in_params.sample_rate != 0) + ctx_priv->out_missed_sample += 1; + + ret = fsl_easrc_write_pf_coeff_mem(easrc, i, + ctx_priv->st1_coeff, + ctx_priv->st1_num_taps, + ctx_priv->st1_addexp); + if (ret) + goto disable_mem_clk; + + ret = fsl_easrc_write_pf_coeff_mem(easrc, i, + ctx_priv->st2_coeff, + ctx_priv->st2_num_taps, + ctx_priv->st2_addexp); + if (ret) + goto disable_mem_clk; + } + +skip_load: + return 0; + +disable_mem_clk: + clk_disable_unprepare(easrc->mem_clk); + return ret; +} +#endif /* CONFIG_PM */ + +static const struct dev_pm_ops fsl_easrc_pm_ops = { + SET_RUNTIME_PM_OPS(fsl_easrc_runtime_suspend, + fsl_easrc_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver fsl_easrc_driver = { + .probe = fsl_easrc_probe, + .remove = fsl_easrc_remove, + .driver = { + .name = "fsl-easrc", + .pm = &fsl_easrc_pm_ops, + .of_match_table = fsl_easrc_dt_ids, + }, +}; +module_platform_driver(fsl_easrc_driver); + +MODULE_DESCRIPTION("NXP Enhanced Asynchronous Sample Rate (eASRC) driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_easrc.h b/sound/soc/fsl/fsl_easrc.h new file mode 100644 index 000000000000..30620d56252c --- /dev/null +++ b/sound/soc/fsl/fsl_easrc.h @@ -0,0 +1,651 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 NXP + */ + +#ifndef _FSL_EASRC_H +#define _FSL_EASRC_H + +#include +#include + +#include "fsl_asrc_common.h" + +/* EASRC Register Map */ + +/* ASRC Input Write FIFO */ +#define REG_EASRC_WRFIFO(ctx) (0x000 + 4 * (ctx)) +/* ASRC Output Read FIFO */ +#define REG_EASRC_RDFIFO(ctx) (0x010 + 4 * (ctx)) +/* ASRC Context Control */ +#define REG_EASRC_CC(ctx) (0x020 + 4 * (ctx)) +/* ASRC Context Control Extended 1 */ +#define REG_EASRC_CCE1(ctx) (0x030 + 4 * (ctx)) +/* ASRC Context Control Extended 2 */ +#define REG_EASRC_CCE2(ctx) (0x040 + 4 * (ctx)) +/* ASRC Control Input Access */ +#define REG_EASRC_CIA(ctx) (0x050 + 4 * (ctx)) +/* ASRC Datapath Processor Control Slot0 */ +#define REG_EASRC_DPCS0R0(ctx) (0x060 + 4 * (ctx)) +#define REG_EASRC_DPCS0R1(ctx) (0x070 + 4 * (ctx)) +#define REG_EASRC_DPCS0R2(ctx) (0x080 + 4 * (ctx)) +#define REG_EASRC_DPCS0R3(ctx) (0x090 + 4 * (ctx)) +/* ASRC Datapath Processor Control Slot1 */ +#define REG_EASRC_DPCS1R0(ctx) (0x0A0 + 4 * (ctx)) +#define REG_EASRC_DPCS1R1(ctx) (0x0B0 + 4 * (ctx)) +#define REG_EASRC_DPCS1R2(ctx) (0x0C0 + 4 * (ctx)) +#define REG_EASRC_DPCS1R3(ctx) (0x0D0 + 4 * (ctx)) +/* ASRC Context Output Control */ +#define REG_EASRC_COC(ctx) (0x0E0 + 4 * (ctx)) +/* ASRC Control Output Access */ +#define REG_EASRC_COA(ctx) (0x0F0 + 4 * (ctx)) +/* ASRC Sample FIFO Status */ +#define REG_EASRC_SFS(ctx) (0x100 + 4 * (ctx)) +/* ASRC Resampling Ratio Low */ +#define REG_EASRC_RRL(ctx) (0x110 + 8 * (ctx)) +/* ASRC Resampling Ratio High */ +#define REG_EASRC_RRH(ctx) (0x114 + 8 * (ctx)) +/* ASRC Resampling Ratio Update Control */ +#define REG_EASRC_RUC(ctx) (0x130 + 4 * (ctx)) +/* ASRC Resampling Ratio Update Rate */ +#define REG_EASRC_RUR(ctx) (0x140 + 4 * (ctx)) +/* ASRC Resampling Center Tap Coefficient Low */ +#define REG_EASRC_RCTCL (0x150) +/* ASRC Resampling Center Tap Coefficient High */ +#define REG_EASRC_RCTCH (0x154) +/* ASRC Prefilter Coefficient FIFO */ +#define REG_EASRC_PCF(ctx) (0x160 + 4 * (ctx)) +/* ASRC Context Resampling Coefficient Memory */ +#define REG_EASRC_CRCM 0x170 +/* ASRC Context Resampling Coefficient Control*/ +#define REG_EASRC_CRCC 0x174 +/* ASRC Interrupt Control */ +#define REG_EASRC_IRQC 0x178 +/* ASRC Interrupt Status Flags */ +#define REG_EASRC_IRQF 0x17C +/* ASRC Channel Status 0 */ +#define REG_EASRC_CS0(ctx) (0x180 + 4 * (ctx)) +/* ASRC Channel Status 1 */ +#define REG_EASRC_CS1(ctx) (0x190 + 4 * (ctx)) +/* ASRC Channel Status 2 */ +#define REG_EASRC_CS2(ctx) (0x1A0 + 4 * (ctx)) +/* ASRC Channel Status 3 */ +#define REG_EASRC_CS3(ctx) (0x1B0 + 4 * (ctx)) +/* ASRC Channel Status 4 */ +#define REG_EASRC_CS4(ctx) (0x1C0 + 4 * (ctx)) +/* ASRC Channel Status 5 */ +#define REG_EASRC_CS5(ctx) (0x1D0 + 4 * (ctx)) +/* ASRC Debug Control Register */ +#define REG_EASRC_DBGC 0x1E0 +/* ASRC Debug Status Register */ +#define REG_EASRC_DBGS 0x1E4 + +#define REG_EASRC_FIFO(x, ctx) (x == IN ? REG_EASRC_WRFIFO(ctx) \ + : REG_EASRC_RDFIFO(ctx)) + +/* ASRC Context Control (CC) */ +#define EASRC_CC_EN_SHIFT 31 +#define EASRC_CC_EN_MASK BIT(EASRC_CC_EN_SHIFT) +#define EASRC_CC_EN BIT(EASRC_CC_EN_SHIFT) +#define EASRC_CC_STOP_SHIFT 29 +#define EASRC_CC_STOP_MASK BIT(EASRC_CC_STOP_SHIFT) +#define EASRC_CC_STOP BIT(EASRC_CC_STOP_SHIFT) +#define EASRC_CC_FWMDE_SHIFT 28 +#define EASRC_CC_FWMDE_MASK BIT(EASRC_CC_FWMDE_SHIFT) +#define EASRC_CC_FWMDE BIT(EASRC_CC_FWMDE_SHIFT) +#define EASRC_CC_FIFO_WTMK_SHIFT 16 +#define EASRC_CC_FIFO_WTMK_WIDTH 7 +#define EASRC_CC_FIFO_WTMK_MASK ((BIT(EASRC_CC_FIFO_WTMK_WIDTH) - 1) \ + << EASRC_CC_FIFO_WTMK_SHIFT) +#define EASRC_CC_FIFO_WTMK(v) (((v) << EASRC_CC_FIFO_WTMK_SHIFT) \ + & EASRC_CC_FIFO_WTMK_MASK) +#define EASRC_CC_SAMPLE_POS_SHIFT 11 +#define EASRC_CC_SAMPLE_POS_WIDTH 5 +#define EASRC_CC_SAMPLE_POS_MASK ((BIT(EASRC_CC_SAMPLE_POS_WIDTH) - 1) \ + << EASRC_CC_SAMPLE_POS_SHIFT) +#define EASRC_CC_SAMPLE_POS(v) (((v) << EASRC_CC_SAMPLE_POS_SHIFT) \ + & EASRC_CC_SAMPLE_POS_MASK) +#define EASRC_CC_ENDIANNESS_SHIFT 10 +#define EASRC_CC_ENDIANNESS_MASK BIT(EASRC_CC_ENDIANNESS_SHIFT) +#define EASRC_CC_ENDIANNESS BIT(EASRC_CC_ENDIANNESS_SHIFT) +#define EASRC_CC_BPS_SHIFT 8 +#define EASRC_CC_BPS_WIDTH 2 +#define EASRC_CC_BPS_MASK ((BIT(EASRC_CC_BPS_WIDTH) - 1) \ + << EASRC_CC_BPS_SHIFT) +#define EASRC_CC_BPS(v) (((v) << EASRC_CC_BPS_SHIFT) \ + & EASRC_CC_BPS_MASK) +#define EASRC_CC_FMT_SHIFT 7 +#define EASRC_CC_FMT_MASK BIT(EASRC_CC_FMT_SHIFT) +#define EASRC_CC_FMT BIT(EASRC_CC_FMT_SHIFT) +#define EASRC_CC_INSIGN_SHIFT 6 +#define EASRC_CC_INSIGN_MASK BIT(EASRC_CC_INSIGN_SHIFT) +#define EASRC_CC_INSIGN BIT(EASRC_CC_INSIGN_SHIFT) +#define EASRC_CC_CHEN_SHIFT 0 +#define EASRC_CC_CHEN_WIDTH 5 +#define EASRC_CC_CHEN_MASK ((BIT(EASRC_CC_CHEN_WIDTH) - 1) \ + << EASRC_CC_CHEN_SHIFT) +#define EASRC_CC_CHEN(v) (((v) << EASRC_CC_CHEN_SHIFT) \ + & EASRC_CC_CHEN_MASK) + +/* ASRC Context Control Extended 1 (CCE1) */ +#define EASRC_CCE1_COEF_WS_SHIFT 25 +#define EASRC_CCE1_COEF_WS_MASK BIT(EASRC_CCE1_COEF_WS_SHIFT) +#define EASRC_CCE1_COEF_WS BIT(EASRC_CCE1_COEF_WS_SHIFT) +#define EASRC_CCE1_COEF_MEM_RST_SHIFT 24 +#define EASRC_CCE1_COEF_MEM_RST_MASK BIT(EASRC_CCE1_COEF_MEM_RST_SHIFT) +#define EASRC_CCE1_COEF_MEM_RST BIT(EASRC_CCE1_COEF_MEM_RST_SHIFT) +#define EASRC_CCE1_PF_EXP_SHIFT 16 +#define EASRC_CCE1_PF_EXP_WIDTH 8 +#define EASRC_CCE1_PF_EXP_MASK ((BIT(EASRC_CCE1_PF_EXP_WIDTH) - 1) \ + << EASRC_CCE1_PF_EXP_SHIFT) +#define EASRC_CCE1_PF_EXP(v) (((v) << EASRC_CCE1_PF_EXP_SHIFT) \ + & EASRC_CCE1_PF_EXP_MASK) +#define EASRC_CCE1_PF_ST1_WBFP_SHIFT 9 +#define EASRC_CCE1_PF_ST1_WBFP_MASK BIT(EASRC_CCE1_PF_ST1_WBFP_SHIFT) +#define EASRC_CCE1_PF_ST1_WBFP BIT(EASRC_CCE1_PF_ST1_WBFP_SHIFT) +#define EASRC_CCE1_PF_TSEN_SHIFT 8 +#define EASRC_CCE1_PF_TSEN_MASK BIT(EASRC_CCE1_PF_TSEN_SHIFT) +#define EASRC_CCE1_PF_TSEN BIT(EASRC_CCE1_PF_TSEN_SHIFT) +#define EASRC_CCE1_RS_BYPASS_SHIFT 7 +#define EASRC_CCE1_RS_BYPASS_MASK BIT(EASRC_CCE1_RS_BYPASS_SHIFT) +#define EASRC_CCE1_RS_BYPASS BIT(EASRC_CCE1_RS_BYPASS_SHIFT) +#define EASRC_CCE1_PF_BYPASS_SHIFT 6 +#define EASRC_CCE1_PF_BYPASS_MASK BIT(EASRC_CCE1_PF_BYPASS_SHIFT) +#define EASRC_CCE1_PF_BYPASS BIT(EASRC_CCE1_PF_BYPASS_SHIFT) +#define EASRC_CCE1_RS_STOP_SHIFT 5 +#define EASRC_CCE1_RS_STOP_MASK BIT(EASRC_CCE1_RS_STOP_SHIFT) +#define EASRC_CCE1_RS_STOP BIT(EASRC_CCE1_RS_STOP_SHIFT) +#define EASRC_CCE1_PF_STOP_SHIFT 4 +#define EASRC_CCE1_PF_STOP_MASK BIT(EASRC_CCE1_PF_STOP_SHIFT) +#define EASRC_CCE1_PF_STOP BIT(EASRC_CCE1_PF_STOP_SHIFT) +#define EASRC_CCE1_RS_INIT_SHIFT 2 +#define EASRC_CCE1_RS_INIT_WIDTH 2 +#define EASRC_CCE1_RS_INIT_MASK ((BIT(EASRC_CCE1_RS_INIT_WIDTH) - 1) \ + << EASRC_CCE1_RS_INIT_SHIFT) +#define EASRC_CCE1_RS_INIT(v) (((v) << EASRC_CCE1_RS_INIT_SHIFT) \ + & EASRC_CCE1_RS_INIT_MASK) +#define EASRC_CCE1_PF_INIT_SHIFT 0 +#define EASRC_CCE1_PF_INIT_WIDTH 2 +#define EASRC_CCE1_PF_INIT_MASK ((BIT(EASRC_CCE1_PF_INIT_WIDTH) - 1) \ + << EASRC_CCE1_PF_INIT_SHIFT) +#define EASRC_CCE1_PF_INIT(v) (((v) << EASRC_CCE1_PF_INIT_SHIFT) \ + & EASRC_CCE1_PF_INIT_MASK) + +/* ASRC Context Control Extended 2 (CCE2) */ +#define EASRC_CCE2_ST2_TAPS_SHIFT 16 +#define EASRC_CCE2_ST2_TAPS_WIDTH 9 +#define EASRC_CCE2_ST2_TAPS_MASK ((BIT(EASRC_CCE2_ST2_TAPS_WIDTH) - 1) \ + << EASRC_CCE2_ST2_TAPS_SHIFT) +#define EASRC_CCE2_ST2_TAPS(v) (((v) << EASRC_CCE2_ST2_TAPS_SHIFT) \ + & EASRC_CCE2_ST2_TAPS_MASK) +#define EASRC_CCE2_ST1_TAPS_SHIFT 0 +#define EASRC_CCE2_ST1_TAPS_WIDTH 9 +#define EASRC_CCE2_ST1_TAPS_MASK ((BIT(EASRC_CCE2_ST1_TAPS_WIDTH) - 1) \ + << EASRC_CCE2_ST1_TAPS_SHIFT) +#define EASRC_CCE2_ST1_TAPS(v) (((v) << EASRC_CCE2_ST1_TAPS_SHIFT) \ + & EASRC_CCE2_ST1_TAPS_MASK) + +/* ASRC Control Input Access (CIA) */ +#define EASRC_CIA_ITER_SHIFT 16 +#define EASRC_CIA_ITER_WIDTH 6 +#define EASRC_CIA_ITER_MASK ((BIT(EASRC_CIA_ITER_WIDTH) - 1) \ + << EASRC_CIA_ITER_SHIFT) +#define EASRC_CIA_ITER(v) (((v) << EASRC_CIA_ITER_SHIFT) \ + & EASRC_CIA_ITER_MASK) +#define EASRC_CIA_GRLEN_SHIFT 8 +#define EASRC_CIA_GRLEN_WIDTH 6 +#define EASRC_CIA_GRLEN_MASK ((BIT(EASRC_CIA_GRLEN_WIDTH) - 1) \ + << EASRC_CIA_GRLEN_SHIFT) +#define EASRC_CIA_GRLEN(v) (((v) << EASRC_CIA_GRLEN_SHIFT) \ + & EASRC_CIA_GRLEN_MASK) +#define EASRC_CIA_ACCLEN_SHIFT 0 +#define EASRC_CIA_ACCLEN_WIDTH 6 +#define EASRC_CIA_ACCLEN_MASK ((BIT(EASRC_CIA_ACCLEN_WIDTH) - 1) \ + << EASRC_CIA_ACCLEN_SHIFT) +#define EASRC_CIA_ACCLEN(v) (((v) << EASRC_CIA_ACCLEN_SHIFT) \ + & EASRC_CIA_ACCLEN_MASK) + +/* ASRC Datapath Processor Control Slot0 Register0 (DPCS0R0) */ +#define EASRC_DPCS0R0_MAXCH_SHIFT 24 +#define EASRC_DPCS0R0_MAXCH_WIDTH 5 +#define EASRC_DPCS0R0_MAXCH_MASK ((BIT(EASRC_DPCS0R0_MAXCH_WIDTH) - 1) \ + << EASRC_DPCS0R0_MAXCH_SHIFT) +#define EASRC_DPCS0R0_MAXCH(v) (((v) << EASRC_DPCS0R0_MAXCH_SHIFT) \ + & EASRC_DPCS0R0_MAXCH_MASK) +#define EASRC_DPCS0R0_MINCH_SHIFT 16 +#define EASRC_DPCS0R0_MINCH_WIDTH 5 +#define EASRC_DPCS0R0_MINCH_MASK ((BIT(EASRC_DPCS0R0_MINCH_WIDTH) - 1) \ + << EASRC_DPCS0R0_MINCH_SHIFT) +#define EASRC_DPCS0R0_MINCH(v) (((v) << EASRC_DPCS0R0_MINCH_SHIFT) \ + & EASRC_DPCS0R0_MINCH_MASK) +#define EASRC_DPCS0R0_NUMCH_SHIFT 8 +#define EASRC_DPCS0R0_NUMCH_WIDTH 5 +#define EASRC_DPCS0R0_NUMCH_MASK ((BIT(EASRC_DPCS0R0_NUMCH_WIDTH) - 1) \ + << EASRC_DPCS0R0_NUMCH_SHIFT) +#define EASRC_DPCS0R0_NUMCH(v) (((v) << EASRC_DPCS0R0_NUMCH_SHIFT) \ + & EASRC_DPCS0R0_NUMCH_MASK) +#define EASRC_DPCS0R0_CTXNUM_SHIFT 1 +#define EASRC_DPCS0R0_CTXNUM_WIDTH 2 +#define EASRC_DPCS0R0_CTXNUM_MASK ((BIT(EASRC_DPCS0R0_CTXNUM_WIDTH) - 1) \ + << EASRC_DPCS0R0_CTXNUM_SHIFT) +#define EASRC_DPCS0R0_CTXNUM(v) (((v) << EASRC_DPCS0R0_CTXNUM_SHIFT) \ + & EASRC_DPCS0R0_CTXNUM_MASK) +#define EASRC_DPCS0R0_EN_SHIFT 0 +#define EASRC_DPCS0R0_EN_MASK BIT(EASRC_DPCS0R0_EN_SHIFT) +#define EASRC_DPCS0R0_EN BIT(EASRC_DPCS0R0_EN_SHIFT) + +/* ASRC Datapath Processor Control Slot0 Register1 (DPCS0R1) */ +#define EASRC_DPCS0R1_ST1_EXP_SHIFT 0 +#define EASRC_DPCS0R1_ST1_EXP_WIDTH 13 +#define EASRC_DPCS0R1_ST1_EXP_MASK ((BIT(EASRC_DPCS0R1_ST1_EXP_WIDTH) - 1) \ + << EASRC_DPCS0R1_ST1_EXP_SHIFT) +#define EASRC_DPCS0R1_ST1_EXP(v) (((v) << EASRC_DPCS0R1_ST1_EXP_SHIFT) \ + & EASRC_DPCS0R1_ST1_EXP_MASK) + +/* ASRC Datapath Processor Control Slot0 Register2 (DPCS0R2) */ +#define EASRC_DPCS0R2_ST1_MA_SHIFT 16 +#define EASRC_DPCS0R2_ST1_MA_WIDTH 13 +#define EASRC_DPCS0R2_ST1_MA_MASK ((BIT(EASRC_DPCS0R2_ST1_MA_WIDTH) - 1) \ + << EASRC_DPCS0R2_ST1_MA_SHIFT) +#define EASRC_DPCS0R2_ST1_MA(v) (((v) << EASRC_DPCS0R2_ST1_MA_SHIFT) \ + & EASRC_DPCS0R2_ST1_MA_MASK) +#define EASRC_DPCS0R2_ST1_SA_SHIFT 0 +#define EASRC_DPCS0R2_ST1_SA_WIDTH 13 +#define EASRC_DPCS0R2_ST1_SA_MASK ((BIT(EASRC_DPCS0R2_ST1_SA_WIDTH) - 1) \ + << EASRC_DPCS0R2_ST1_SA_SHIFT) +#define EASRC_DPCS0R2_ST1_SA(v) (((v) << EASRC_DPCS0R2_ST1_SA_SHIFT) \ + & EASRC_DPCS0R2_ST1_SA_MASK) + +/* ASRC Datapath Processor Control Slot0 Register3 (DPCS0R3) */ +#define EASRC_DPCS0R3_ST2_MA_SHIFT 16 +#define EASRC_DPCS0R3_ST2_MA_WIDTH 13 +#define EASRC_DPCS0R3_ST2_MA_MASK ((BIT(EASRC_DPCS0R3_ST2_MA_WIDTH) - 1) \ + << EASRC_DPCS0R3_ST2_MA_SHIFT) +#define EASRC_DPCS0R3_ST2_MA(v) (((v) << EASRC_DPCS0R3_ST2_MA_SHIFT) \ + & EASRC_DPCS0R3_ST2_MA_MASK) +#define EASRC_DPCS0R3_ST2_SA_SHIFT 0 +#define EASRC_DPCS0R3_ST2_SA_WIDTH 13 +#define EASRC_DPCS0R3_ST2_SA_MASK ((BIT(EASRC_DPCS0R3_ST2_SA_WIDTH) - 1) \ + << EASRC_DPCS0R3_ST2_SA_SHIFT) +#define EASRC_DPCS0R3_ST2_SA(v) (((v) << EASRC_DPCS0R3_ST2_SA_SHIFT) \ + & EASRC_DPCS0R3_ST2_SA_MASK) + +/* ASRC Context Output Control (COC) */ +#define EASRC_COC_FWMDE_SHIFT 28 +#define EASRC_COC_FWMDE_MASK BIT(EASRC_COC_FWMDE_SHIFT) +#define EASRC_COC_FWMDE BIT(EASRC_COC_FWMDE_SHIFT) +#define EASRC_COC_FIFO_WTMK_SHIFT 16 +#define EASRC_COC_FIFO_WTMK_WIDTH 7 +#define EASRC_COC_FIFO_WTMK_MASK ((BIT(EASRC_COC_FIFO_WTMK_WIDTH) - 1) \ + << EASRC_COC_FIFO_WTMK_SHIFT) +#define EASRC_COC_FIFO_WTMK(v) (((v) << EASRC_COC_FIFO_WTMK_SHIFT) \ + & EASRC_COC_FIFO_WTMK_MASK) +#define EASRC_COC_SAMPLE_POS_SHIFT 11 +#define EASRC_COC_SAMPLE_POS_WIDTH 5 +#define EASRC_COC_SAMPLE_POS_MASK ((BIT(EASRC_COC_SAMPLE_POS_WIDTH) - 1) \ + << EASRC_COC_SAMPLE_POS_SHIFT) +#define EASRC_COC_SAMPLE_POS(v) (((v) << EASRC_COC_SAMPLE_POS_SHIFT) \ + & EASRC_COC_SAMPLE_POS_MASK) +#define EASRC_COC_ENDIANNESS_SHIFT 10 +#define EASRC_COC_ENDIANNESS_MASK BIT(EASRC_COC_ENDIANNESS_SHIFT) +#define EASRC_COC_ENDIANNESS BIT(EASRC_COC_ENDIANNESS_SHIFT) +#define EASRC_COC_BPS_SHIFT 8 +#define EASRC_COC_BPS_WIDTH 2 +#define EASRC_COC_BPS_MASK ((BIT(EASRC_COC_BPS_WIDTH) - 1) \ + << EASRC_COC_BPS_SHIFT) +#define EASRC_COC_BPS(v) (((v) << EASRC_COC_BPS_SHIFT) \ + & EASRC_COC_BPS_MASK) +#define EASRC_COC_FMT_SHIFT 7 +#define EASRC_COC_FMT_MASK BIT(EASRC_COC_FMT_SHIFT) +#define EASRC_COC_FMT BIT(EASRC_COC_FMT_SHIFT) +#define EASRC_COC_OUTSIGN_SHIFT 6 +#define EASRC_COC_OUTSIGN_MASK BIT(EASRC_COC_OUTSIGN_SHIFT) +#define EASRC_COC_OUTSIGN_OUT BIT(EASRC_COC_OUTSIGN_SHIFT) +#define EASRC_COC_IEC_VDATA_SHIFT 2 +#define EASRC_COC_IEC_VDATA_MASK BIT(EASRC_COC_IEC_VDATA_SHIFT) +#define EASRC_COC_IEC_VDATA BIT(EASRC_COC_IEC_VDATA_SHIFT) +#define EASRC_COC_IEC_EN_SHIFT 1 +#define EASRC_COC_IEC_EN_MASK BIT(EASRC_COC_IEC_EN_SHIFT) +#define EASRC_COC_IEC_EN BIT(EASRC_COC_IEC_EN_SHIFT) +#define EASRC_COC_DITHER_EN_SHIFT 0 +#define EASRC_COC_DITHER_EN_MASK BIT(EASRC_COC_DITHER_EN_SHIFT) +#define EASRC_COC_DITHER_EN BIT(EASRC_COC_DITHER_EN_SHIFT) + +/* ASRC Control Output Access (COA) */ +#define EASRC_COA_ITER_SHIFT 16 +#define EASRC_COA_ITER_WIDTH 6 +#define EASRC_COA_ITER_MASK ((BIT(EASRC_COA_ITER_WIDTH) - 1) \ + << EASRC_COA_ITER_SHIFT) +#define EASRC_COA_ITER(v) (((v) << EASRC_COA_ITER_SHIFT) \ + & EASRC_COA_ITER_MASK) +#define EASRC_COA_GRLEN_SHIFT 8 +#define EASRC_COA_GRLEN_WIDTH 6 +#define EASRC_COA_GRLEN_MASK ((BIT(EASRC_COA_GRLEN_WIDTH) - 1) \ + << EASRC_COA_GRLEN_SHIFT) +#define EASRC_COA_GRLEN(v) (((v) << EASRC_COA_GRLEN_SHIFT) \ + & EASRC_COA_GRLEN_MASK) +#define EASRC_COA_ACCLEN_SHIFT 0 +#define EASRC_COA_ACCLEN_WIDTH 6 +#define EASRC_COA_ACCLEN_MASK ((BIT(EASRC_COA_ACCLEN_WIDTH) - 1) \ + << EASRC_COA_ACCLEN_SHIFT) +#define EASRC_COA_ACCLEN(v) (((v) << EASRC_COA_ACCLEN_SHIFT) \ + & EASRC_COA_ACCLEN_MASK) + +/* ASRC Sample FIFO Status (SFS) */ +#define EASRC_SFS_IWTMK_SHIFT 23 +#define EASRC_SFS_IWTMK_MASK BIT(EASRC_SFS_IWTMK_SHIFT) +#define EASRC_SFS_IWTMK BIT(EASRC_SFS_IWTMK_SHIFT) +#define EASRC_SFS_NSGI_SHIFT 16 +#define EASRC_SFS_NSGI_WIDTH 7 +#define EASRC_SFS_NSGI_MASK ((BIT(EASRC_SFS_NSGI_WIDTH) - 1) \ + << EASRC_SFS_NSGI_SHIFT) +#define EASRC_SFS_NSGI(v) (((v) << EASRC_SFS_NSGI_SHIFT) \ + & EASRC_SFS_NSGI_MASK) +#define EASRC_SFS_OWTMK_SHIFT 7 +#define EASRC_SFS_OWTMK_MASK BIT(EASRC_SFS_OWTMK_SHIFT) +#define EASRC_SFS_OWTMK BIT(EASRC_SFS_OWTMK_SHIFT) +#define EASRC_SFS_NSGO_SHIFT 0 +#define EASRC_SFS_NSGO_WIDTH 7 +#define EASRC_SFS_NSGO_MASK ((BIT(EASRC_SFS_NSGO_WIDTH) - 1) \ + << EASRC_SFS_NSGO_SHIFT) +#define EASRC_SFS_NSGO(v) (((v) << EASRC_SFS_NSGO_SHIFT) \ + & EASRC_SFS_NSGO_MASK) + +/* ASRC Resampling Ratio Low (RRL) */ +#define EASRC_RRL_RS_RL_SHIFT 0 +#define EASRC_RRL_RS_RL_WIDTH 32 +#define EASRC_RRL_RS_RL(v) ((v) << EASRC_RRL_RS_RL_SHIFT) + +/* ASRC Resampling Ratio High (RRH) */ +#define EASRC_RRH_RS_VLD_SHIFT 31 +#define EASRC_RRH_RS_VLD_MASK BIT(EASRC_RRH_RS_VLD_SHIFT) +#define EASRC_RRH_RS_VLD BIT(EASRC_RRH_RS_VLD_SHIFT) +#define EASRC_RRH_RS_RH_SHIFT 0 +#define EASRC_RRH_RS_RH_WIDTH 12 +#define EASRC_RRH_RS_RH_MASK ((BIT(EASRC_RRH_RS_RH_WIDTH) - 1) \ + << EASRC_RRH_RS_RH_SHIFT) +#define EASRC_RRH_RS_RH(v) (((v) << EASRC_RRH_RS_RH_SHIFT) \ + & EASRC_RRH_RS_RH_MASK) + +/* ASRC Resampling Ratio Update Control (RSUC) */ +#define EASRC_RSUC_RS_RM_SHIFT 0 +#define EASRC_RSUC_RS_RM_WIDTH 32 +#define EASRC_RSUC_RS_RM(v) ((v) << EASRC_RSUC_RS_RM_SHIFT) + +/* ASRC Resampling Ratio Update Rate (RRUR) */ +#define EASRC_RRUR_RRR_SHIFT 0 +#define EASRC_RRUR_RRR_WIDTH 31 +#define EASRC_RRUR_RRR_MASK ((BIT(EASRC_RRUR_RRR_WIDTH) - 1) \ + << EASRC_RRUR_RRR_SHIFT) +#define EASRC_RRUR_RRR(v) (((v) << EASRC_RRUR_RRR_SHIFT) \ + & EASRC_RRUR_RRR_MASK) + +/* ASRC Resampling Center Tap Coefficient Low (RCTCL) */ +#define EASRC_RCTCL_RS_CL_SHIFT 0 +#define EASRC_RCTCL_RS_CL_WIDTH 32 +#define EASRC_RCTCL_RS_CL(v) ((v) << EASRC_RCTCL_RS_CL_SHIFT) + +/* ASRC Resampling Center Tap Coefficient High (RCTCH) */ +#define EASRC_RCTCH_RS_CH_SHIFT 0 +#define EASRC_RCTCH_RS_CH_WIDTH 32 +#define EASRC_RCTCH_RS_CH(v) ((v) << EASRC_RCTCH_RS_CH_SHIFT) + +/* ASRC Prefilter Coefficient FIFO (PCF) */ +#define EASRC_PCF_CD_SHIFT 0 +#define EASRC_PCF_CD_WIDTH 32 +#define EASRC_PCF_CD(v) ((v) << EASRC_PCF_CD_SHIFT) + +/* ASRC Context Resampling Coefficient Memory (CRCM) */ +#define EASRC_CRCM_RS_CWD_SHIFT 0 +#define EASRC_CRCM_RS_CWD_WIDTH 32 +#define EASRC_CRCM_RS_CWD(v) ((v) << EASRC_CRCM_RS_CWD_SHIFT) + +/* ASRC Context Resampling Coefficient Control (CRCC) */ +#define EASRC_CRCC_RS_CA_SHIFT 16 +#define EASRC_CRCC_RS_CA_WIDTH 11 +#define EASRC_CRCC_RS_CA_MASK ((BIT(EASRC_CRCC_RS_CA_WIDTH) - 1) \ + << EASRC_CRCC_RS_CA_SHIFT) +#define EASRC_CRCC_RS_CA(v) (((v) << EASRC_CRCC_RS_CA_SHIFT) \ + & EASRC_CRCC_RS_CA_MASK) +#define EASRC_CRCC_RS_TAPS_SHIFT 1 +#define EASRC_CRCC_RS_TAPS_WIDTH 2 +#define EASRC_CRCC_RS_TAPS_MASK ((BIT(EASRC_CRCC_RS_TAPS_WIDTH) - 1) \ + << EASRC_CRCC_RS_TAPS_SHIFT) +#define EASRC_CRCC_RS_TAPS(v) (((v) << EASRC_CRCC_RS_TAPS_SHIFT) \ + & EASRC_CRCC_RS_TAPS_MASK) +#define EASRC_CRCC_RS_CPR_SHIFT 0 +#define EASRC_CRCC_RS_CPR_MASK BIT(EASRC_CRCC_RS_CPR_SHIFT) +#define EASRC_CRCC_RS_CPR BIT(EASRC_CRCC_RS_CPR_SHIFT) + +/* ASRC Interrupt_Control (IC) */ +#define EASRC_IRQC_RSDM_SHIFT 8 +#define EASRC_IRQC_RSDM_WIDTH 4 +#define EASRC_IRQC_RSDM_MASK ((BIT(EASRC_IRQC_RSDM_WIDTH) - 1) \ + << EASRC_IRQC_RSDM_SHIFT) +#define EASRC_IRQC_RSDM(v) (((v) << EASRC_IRQC_RSDM_SHIFT) \ + & EASRC_IRQC_RSDM_MASK) +#define EASRC_IRQC_OERM_SHIFT 4 +#define EASRC_IRQC_OERM_WIDTH 4 +#define EASRC_IRQC_OERM_MASK ((BIT(EASRC_IRQC_OERM_WIDTH) - 1) \ + << EASRC_IRQC_OERM_SHIFT) +#define EASRC_IRQC_OERM(v) (((v) << EASRC_IRQC_OERM_SHIFT) \ + & EASRC_IEQC_OERM_MASK) +#define EASRC_IRQC_IOM_SHIFT 0 +#define EASRC_IRQC_IOM_WIDTH 4 +#define EASRC_IRQC_IOM_MASK ((BIT(EASRC_IRQC_IOM_WIDTH) - 1) \ + << EASRC_IRQC_IOM_SHIFT) +#define EASRC_IRQC_IOM(v) (((v) << EASRC_IRQC_IOM_SHIFT) \ + & EASRC_IRQC_IOM_MASK) + +/* ASRC Interrupt Status Flags (ISF) */ +#define EASRC_IRQF_RSD_SHIFT 8 +#define EASRC_IRQF_RSD_WIDTH 4 +#define EASRC_IRQF_RSD_MASK ((BIT(EASRC_IRQF_RSD_WIDTH) - 1) \ + << EASRC_IRQF_RSD_SHIFT) +#define EASRC_IRQF_RSD(v) (((v) << EASRC_IRQF_RSD_SHIFT) \ + & EASRC_IRQF_RSD_MASK) +#define EASRC_IRQF_OER_SHIFT 4 +#define EASRC_IRQF_OER_WIDTH 4 +#define EASRC_IRQF_OER_MASK ((BIT(EASRC_IRQF_OER_WIDTH) - 1) \ + << EASRC_IRQF_OER_SHIFT) +#define EASRC_IRQF_OER(v) (((v) << EASRC_IRQF_OER_SHIFT) \ + & EASRC_IRQF_OER_MASK) +#define EASRC_IRQF_IFO_SHIFT 0 +#define EASRC_IRQF_IFO_WIDTH 4 +#define EASRC_IRQF_IFO_MASK ((BIT(EASRC_IRQF_IFO_WIDTH) - 1) \ + << EASRC_IRQF_IFO_SHIFT) +#define EASRC_IRQF_IFO(v) (((v) << EASRC_IRQF_IFO_SHIFT) \ + & EASRC_IRQF_IFO_MASK) + +/* ASRC Context Channel STAT */ +#define EASRC_CSx_CSx_SHIFT 0 +#define EASRC_CSx_CSx_WIDTH 32 +#define EASRC_CSx_CSx(v) ((v) << EASRC_CSx_CSx_SHIFT) + +/* ASRC Debug Control Register */ +#define EASRC_DBGC_DMS_SHIFT 0 +#define EASRC_DBGC_DMS_WIDTH 6 +#define EASRC_DBGC_DMS_MASK ((BIT(EASRC_DBGC_DMS_WIDTH) - 1) \ + << EASRC_DBGC_DMS_SHIFT) +#define EASRC_DBGC_DMS(v) (((v) << EASRC_DBGC_DMS_SHIFT) \ + & EASRC_DBGC_DMS_MASK) + +/* ASRC Debug Status Register */ +#define EASRC_DBGS_DS_SHIFT 0 +#define EASRC_DBGS_DS_WIDTH 32 +#define EASRC_DBGS_DS(v) ((v) << EASRC_DBGS_DS_SHIFT) + +/* General Constants */ +#define EASRC_CTX_MAX_NUM 4 +#define EASRC_RS_COEFF_MEM 0 +#define EASRC_PF_COEFF_MEM 1 + +/* Prefilter constants */ +#define EASRC_PF_ST1_ONLY 0 +#define EASRC_PF_TWO_STAGE_MODE 1 +#define EASRC_PF_ST1_COEFF_WR 0 +#define EASRC_PF_ST2_COEFF_WR 1 +#define EASRC_MAX_PF_TAPS 384 + +/* Resampling constants */ +#define EASRC_RS_32_TAPS 0 +#define EASRC_RS_64_TAPS 1 +#define EASRC_RS_128_TAPS 2 + +/* Initialization mode */ +#define EASRC_INIT_MODE_SW_CONTROL 0 +#define EASRC_INIT_MODE_REPLICATE 1 +#define EASRC_INIT_MODE_ZERO_FILL 2 + +/* FIFO watermarks */ +#define FSL_EASRC_INPUTFIFO_WML 0x4 +#define FSL_EASRC_OUTPUTFIFO_WML 0x1 + +#define EASRC_INPUTFIFO_THRESHOLD_MIN 0 +#define EASRC_INPUTFIFO_THRESHOLD_MAX 127 +#define EASRC_OUTPUTFIFO_THRESHOLD_MIN 0 +#define EASRC_OUTPUTFIFO_THRESHOLD_MAX 63 + +#define EASRC_DMA_BUFFER_SIZE (1024 * 48 * 9) +#define EASRC_MAX_BUFFER_SIZE (1024 * 48) + +#define FIRMWARE_MAGIC 0xDEAD +#define FIRMWARE_VERSION 1 + +#define PREFILTER_MEM_LEN 0x1800 + +enum easrc_word_width { + EASRC_WIDTH_16_BIT = 0, + EASRC_WIDTH_20_BIT = 1, + EASRC_WIDTH_24_BIT = 2, + EASRC_WIDTH_32_BIT = 3, +}; + +struct __attribute__((__packed__)) asrc_firmware_hdr { + u32 magic; + u32 interp_scen; + u32 prefil_scen; + u32 firmware_version; +}; + +struct __attribute__((__packed__)) interp_params { + u32 magic; + u32 num_taps; + u32 num_phases; + u64 center_tap; + u64 coeff[8192]; +}; + +struct __attribute__((__packed__)) prefil_params { + u32 magic; + u32 insr; + u32 outsr; + u32 st1_taps; + u32 st2_taps; + u32 st1_exp; + u64 coeff[256]; +}; + +struct dma_block { + void *dma_vaddr; + unsigned int length; + unsigned int max_buf_size; +}; + +struct fsl_easrc_data_fmt { + unsigned int width : 2; + unsigned int endianness : 1; + unsigned int unsign : 1; + unsigned int floating_point : 1; + unsigned int iec958: 1; + unsigned int sample_pos: 5; + unsigned int addexp; +}; + +struct fsl_easrc_io_params { + struct fsl_easrc_data_fmt fmt; + unsigned int group_len; + unsigned int iterations; + unsigned int access_len; + unsigned int fifo_wtmk; + unsigned int sample_rate; + unsigned int sample_format; + unsigned int norm_rate; +}; + +struct fsl_easrc_slot { + bool busy; + int ctx_index; + int slot_index; + int num_channel; /* maximum is 8 */ + int min_channel; + int max_channel; + int pf_mem_used; +}; + +/** + * fsl_easrc_ctx_priv: EASRC context private data + * + * @in_params: input parameter + * @out_params: output parameter + * @st1_num_taps: tap number of stage 1 + * @st2_num_taps: tap number of stage 2 + * @st1_num_exp: exponent number of stage 1 + * @pf_init_mode: prefilter init mode + * @rs_init_mode: resample filter init mode + * @ctx_streams: stream flag of ctx + * @rs_ratio: resampler ratio + * @st1_coeff: pointer of stage 1 coeff + * @st2_coeff: pointer of stage 2 coeff + * @in_filled_sample: input filled sample + * @out_missed_sample: sample missed in output + * @st1_addexp: exponent added for stage1 + * @st2_addexp: exponent added for stage2 + */ +struct fsl_easrc_ctx_priv { + struct fsl_easrc_io_params in_params; + struct fsl_easrc_io_params out_params; + unsigned int st1_num_taps; + unsigned int st2_num_taps; + unsigned int st1_num_exp; + unsigned int pf_init_mode; + unsigned int rs_init_mode; + unsigned int ctx_streams; + u64 rs_ratio; + u64 *st1_coeff; + u64 *st2_coeff; + int in_filled_sample; + int out_missed_sample; + int st1_addexp; + int st2_addexp; +}; + +/** + * fsl_easrc_priv: EASRC private data + * + * @slot: slot setting + * @firmware_hdr: the header of firmware + * @interp: pointer to interpolation filter coeff + * @prefil: pointer to prefilter coeff + * @fw: firmware of coeff table + * @fw_name: firmware name + * @rs_num_taps: resample filter taps, 32, 64, or 128 + * @bps_iec958: bits per sample of iec958 + * @rs_coeff: resampler coefficient + * @const_coeff: one tap prefilter coefficient + * @firmware_loaded: firmware is loaded + */ +struct fsl_easrc_priv { + struct fsl_easrc_slot slot[EASRC_CTX_MAX_NUM][2]; + struct asrc_firmware_hdr *firmware_hdr; + struct interp_params *interp; + struct prefil_params *prefil; + const struct firmware *fw; + const char *fw_name; + unsigned int rs_num_taps; + unsigned int bps_iec958[EASRC_CTX_MAX_NUM]; + u64 *rs_coeff; + u64 const_coeff; + int firmware_loaded; +}; +#endif /* _FSL_EASRC_H */ From c6cb522c1461eee41f086839bd3c9cb622cd26ca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:07:50 +0900 Subject: [PATCH 087/428] ASoC: soc-compress: add snd_compress_ops Current snd_soc_component_driver has compr_ops, and each driver can have callback via it. But, it is mainly created for ALSA, thus, it doesn't have "component" as parameter. Thus, each callback can't know it is called for which component. Each callback currently is getting "component" by using snd_soc_rtdcom_lookup() with driver name. --- ALSA SoC --- ... if (component->driver->compr_ops && component->driver->compr_ops->open) => return component->driver->compr_ops->open(stream); ... --- driver --- static int xxx_open(struct snd_compr_stream *stream) { struct snd_soc_pcm_runtime *rtd = stream->private_data; => struct snd_soc_component *component = snd_soc_rtdcom_lookup(..); ... } It works today, but, will not work in the future if we support multi CPU/Codec/Platform, because 1 rtd might have multiple same driver name component. To solve this issue, each callback need to be called with component. We already have many component driver callbacks. This patch adds new snd_compress_ops, and call it with "component". --- ALSA SoC --- ... if (component->driver->compress_ops->open) => return component->driver->compress_ops->open( component, substream); ~~~~~~~~~ ... --- driver --- static int xxx_open(struct snd_soc_component *component, struct snd_compr_stream *stream) { => /* it don't need to use snd_soc_rtdcom_lookup() */ ... } Signed-off-by: Kuninori Morimoto Tested-by: Charles Keepax Reviewed-by: Charles Keepax Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87v9luvdmh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 41 ++++++++- sound/soc/soc-compress.c | 152 ++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+), 1 deletion(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 154d02fbbfed..9122b11f51e9 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -25,6 +25,44 @@ order++) /* component interface */ +struct snd_compress_ops { + int (*open)(struct snd_soc_component *component, + struct snd_compr_stream *stream); + int (*free)(struct snd_soc_component *component, + struct snd_compr_stream *stream); + int (*set_params)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_params *params); + int (*get_params)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_codec *params); + int (*set_metadata)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_metadata *metadata); + int (*get_metadata)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_metadata *metadata); + int (*trigger)(struct snd_soc_component *component, + struct snd_compr_stream *stream, int cmd); + int (*pointer)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_tstamp *tstamp); + int (*copy)(struct snd_soc_component *component, + struct snd_compr_stream *stream, char __user *buf, + size_t count); + int (*mmap)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct vm_area_struct *vma); + int (*ack)(struct snd_soc_component *component, + struct snd_compr_stream *stream, size_t bytes); + int (*get_caps)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_caps *caps); + int (*get_codec_caps)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_codec_caps *codec); +}; + struct snd_soc_component_driver { const char *name; @@ -108,7 +146,8 @@ struct snd_soc_component_driver { struct snd_pcm_substream *substream, struct vm_area_struct *vma); - const struct snd_compr_ops *compr_ops; + const struct snd_compr_ops *compr_ops; /* remove me */ + const struct snd_compress_ops *compress_ops; /* probe ordering - for components with runtime dependencies */ int probe_order; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 3f77c0208e09..343de969179e 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -28,6 +28,23 @@ static int soc_compr_components_open(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret; + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->open) + continue; + + ret = component->driver->compress_ops->open(component, cstream); + if (ret < 0) { + dev_err(component->dev, + "Compress ASoC: can't open platform %s: %d\n", + component->name, ret); + + *last = component; + return ret; + } + } + + /* remvoe me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->open) @@ -55,6 +72,18 @@ static int soc_compr_components_free(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i; + for_each_rtd_components(rtd, i, component) { + if (component == last) + break; + + if (!component->driver->compress_ops || + !component->driver->compress_ops->free) + continue; + + component->driver->compress_ops->free(component, cstream); + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (component == last) break; @@ -327,6 +356,18 @@ static int soc_compr_components_trigger(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret; + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->trigger) + continue; + + ret = component->driver->compress_ops->trigger( + component, cstream, cmd); + if (ret < 0) + return ret; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->trigger) @@ -429,6 +470,18 @@ static int soc_compr_components_set_params(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret; + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->set_params) + continue; + + ret = component->driver->compress_ops->set_params( + component, cstream, params); + if (ret < 0) + return ret; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->set_params) @@ -569,6 +622,17 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, goto err; } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->get_params) + continue; + + ret = component->driver->compress_ops->get_params( + component, cstream, params); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->get_params) @@ -592,6 +656,17 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->get_caps) + continue; + + ret = component->driver->compress_ops->get_caps( + component, cstream, caps); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->get_caps) @@ -614,6 +689,17 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->get_codec_caps) + continue; + + ret = component->driver->compress_ops->get_codec_caps( + component, cstream, codec); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->get_codec_caps) @@ -643,6 +729,18 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) goto err; } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->ack) + continue; + + ret = component->driver->compress_ops->ack( + component, cstream, bytes); + if (ret < 0) + goto err; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->ack) @@ -671,6 +769,17 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer) cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai); + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->pointer) + continue; + + ret = component->driver->compress_ops->pointer( + component, cstream, tstamp); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->pointer) @@ -693,6 +802,17 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->copy) + continue; + + ret = component->driver->compress_ops->copy( + component, cstream, buf, count); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->copy) @@ -720,6 +840,18 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream, return ret; } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->set_metadata) + continue; + + ret = component->driver->compress_ops->set_metadata( + component, cstream, metadata); + if (ret < 0) + return ret; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->set_metadata) @@ -748,6 +880,16 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, return ret; } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->get_metadata) + continue; + + return component->driver->compress_ops->get_metadata( + component, cstream, metadata); + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->get_metadata) @@ -878,6 +1020,16 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->copy) + continue; + + compr->ops->copy = soc_compr_copy; + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->copy) From 3a5ccf25ee184510980a2c48606f7a004a2c844b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:08:13 +0900 Subject: [PATCH 088/428] ASoC: codec: wm_adsp: use snd_compress_ops We can use snd_compress_ops. Let's switch to use it. Signed-off-by: Kuninori Morimoto Tested-by: Charles Keepax Reviewed-by: Ranjani Sridharan Acked-by: Charles Keepax Link: https://lore.kernel.org/r/87tv1evdlu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l15.c | 9 ++++----- sound/soc/codecs/cs47l24.c | 8 ++++---- sound/soc/codecs/cs47l35.c | 9 ++++----- sound/soc/codecs/cs47l85.c | 9 ++++----- sound/soc/codecs/cs47l90.c | 9 ++++----- sound/soc/codecs/cs47l92.c | 9 ++++----- sound/soc/codecs/wm5102.c | 9 ++++----- sound/soc/codecs/wm5110.c | 8 ++++---- sound/soc/codecs/wm_adsp.c | 18 ++++++++++++------ sound/soc/codecs/wm_adsp.h | 18 ++++++++++++------ 10 files changed, 56 insertions(+), 50 deletions(-) diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index 8d1869bf7f9c..402c6b7c7014 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -1229,11 +1229,10 @@ static struct snd_soc_dai_driver cs47l15_dai[] = { }, }; -static int cs47l15_open(struct snd_compr_stream *stream) +static int cs47l15_open(struct snd_soc_component *component, + 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 cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); struct madera_priv *priv = &cs47l15->core; struct madera *madera = priv->madera; @@ -1329,7 +1328,7 @@ static unsigned int cs47l15_digital_vu[] = { MADERA_DAC_DIGITAL_VOLUME_5R, }; -static const struct snd_compr_ops cs47l15_compr_ops = { +static const struct snd_compress_ops cs47l15_compress_ops = { .open = &cs47l15_open, .free = &wm_adsp_compr_free, .set_params = &wm_adsp_compr_set_params, @@ -1345,7 +1344,7 @@ static const struct snd_soc_component_driver soc_component_dev_cs47l15 = { .set_sysclk = &madera_set_sysclk, .set_pll = &cs47l15_set_fll, .name = DRV_NAME, - .compr_ops = &cs47l15_compr_ops, + .compress_ops = &cs47l15_compress_ops, .controls = cs47l15_snd_controls, .num_controls = ARRAY_SIZE(cs47l15_snd_controls), .dapm_widgets = cs47l15_dapm_widgets, diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 6b0570f59630..f6d173d0120e 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -1068,10 +1068,10 @@ static struct snd_soc_dai_driver cs47l24_dai[] = { }, }; -static int cs47l24_open(struct snd_compr_stream *stream) +static int cs47l24_open(struct snd_soc_component *component, + 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 cs47l24_priv *priv = snd_soc_component_get_drvdata(component); struct arizona *arizona = priv->core.arizona; int n_adsp; @@ -1178,7 +1178,7 @@ static unsigned int cs47l24_digital_vu[] = { ARIZONA_DAC_DIGITAL_VOLUME_4L, }; -static struct snd_compr_ops cs47l24_compr_ops = { +static struct snd_compress_ops cs47l24_compress_ops = { .open = cs47l24_open, .free = wm_adsp_compr_free, .set_params = wm_adsp_compr_set_params, @@ -1194,7 +1194,7 @@ static const struct snd_soc_component_driver soc_component_dev_cs47l24 = { .set_sysclk = arizona_set_sysclk, .set_pll = cs47l24_set_fll, .name = DRV_NAME, - .compr_ops = &cs47l24_compr_ops, + .compress_ops = &cs47l24_compress_ops, .controls = cs47l24_snd_controls, .num_controls = ARRAY_SIZE(cs47l24_snd_controls), .dapm_widgets = cs47l24_dapm_widgets, diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index 18839807c9d1..d7538d50bbd3 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -1504,11 +1504,10 @@ static struct snd_soc_dai_driver cs47l35_dai[] = { }, }; -static int cs47l35_open(struct snd_compr_stream *stream) +static int cs47l35_open(struct snd_soc_component *component, + 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; @@ -1622,7 +1621,7 @@ static unsigned int cs47l35_digital_vu[] = { MADERA_DAC_DIGITAL_VOLUME_5R, }; -static const struct snd_compr_ops cs47l35_compr_ops = { +static const struct snd_compress_ops cs47l35_compress_ops = { .open = &cs47l35_open, .free = &wm_adsp_compr_free, .set_params = &wm_adsp_compr_set_params, @@ -1638,7 +1637,7 @@ static const struct snd_soc_component_driver soc_component_dev_cs47l35 = { .set_sysclk = &madera_set_sysclk, .set_pll = &cs47l35_set_fll, .name = DRV_NAME, - .compr_ops = &cs47l35_compr_ops, + .compress_ops = &cs47l35_compress_ops, .controls = cs47l35_snd_controls, .num_controls = ARRAY_SIZE(cs47l35_snd_controls), .dapm_widgets = cs47l35_dapm_widgets, diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index a575113207f0..9de991adad74 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -2447,11 +2447,10 @@ static struct snd_soc_dai_driver cs47l85_dai[] = { }, }; -static int cs47l85_open(struct snd_compr_stream *stream) +static int cs47l85_open(struct snd_soc_component *component, + 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; @@ -2566,7 +2565,7 @@ static const unsigned int cs47l85_digital_vu[] = { MADERA_DAC_DIGITAL_VOLUME_6R, }; -static const struct snd_compr_ops cs47l85_compr_ops = { +static const struct snd_compress_ops cs47l85_compress_ops = { .open = &cs47l85_open, .free = &wm_adsp_compr_free, .set_params = &wm_adsp_compr_set_params, @@ -2582,7 +2581,7 @@ static const struct snd_soc_component_driver soc_component_dev_cs47l85 = { .set_sysclk = &madera_set_sysclk, .set_pll = &cs47l85_set_fll, .name = DRV_NAME, - .compr_ops = &cs47l85_compr_ops, + .compress_ops = &cs47l85_compress_ops, .controls = cs47l85_snd_controls, .num_controls = ARRAY_SIZE(cs47l85_snd_controls), .dapm_widgets = cs47l85_dapm_widgets, diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 81a1311b14e6..2715b5da0415 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -2358,11 +2358,10 @@ static struct snd_soc_dai_driver cs47l90_dai[] = { }, }; -static int cs47l90_open(struct snd_compr_stream *stream) +static int cs47l90_open(struct snd_soc_component *component, + 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; @@ -2473,7 +2472,7 @@ static unsigned int cs47l90_digital_vu[] = { MADERA_DAC_DIGITAL_VOLUME_5R, }; -static const struct snd_compr_ops cs47l90_compr_ops = { +static const struct snd_compress_ops cs47l90_compress_ops = { .open = &cs47l90_open, .free = &wm_adsp_compr_free, .set_params = &wm_adsp_compr_set_params, @@ -2489,7 +2488,7 @@ static const struct snd_soc_component_driver soc_component_dev_cs47l90 = { .set_sysclk = &madera_set_sysclk, .set_pll = &cs47l90_set_fll, .name = DRV_NAME, - .compr_ops = &cs47l90_compr_ops, + .compress_ops = &cs47l90_compress_ops, .controls = cs47l90_snd_controls, .num_controls = ARRAY_SIZE(cs47l90_snd_controls), .dapm_widgets = cs47l90_dapm_widgets, diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index 15fc213d178d..108d28007185 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -1830,11 +1830,10 @@ static struct snd_soc_dai_driver cs47l92_dai[] = { }, }; -static int cs47l92_open(struct snd_compr_stream *stream) +static int cs47l92_open(struct snd_soc_component *component, + 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 cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); struct madera_priv *priv = &cs47l92->core; struct madera *madera = priv->madera; @@ -1933,7 +1932,7 @@ static unsigned int cs47l92_digital_vu[] = { MADERA_DAC_DIGITAL_VOLUME_5R, }; -static const struct snd_compr_ops cs47l92_compr_ops = { +static const struct snd_compress_ops cs47l92_compress_ops = { .open = &cs47l92_open, .free = &wm_adsp_compr_free, .set_params = &wm_adsp_compr_set_params, @@ -1949,7 +1948,7 @@ static const struct snd_soc_component_driver soc_component_dev_cs47l92 = { .set_sysclk = &madera_set_sysclk, .set_pll = &cs47l92_set_fll, .name = DRV_NAME, - .compr_ops = &cs47l92_compr_ops, + .compress_ops = &cs47l92_compress_ops, .controls = cs47l92_snd_controls, .num_controls = ARRAY_SIZE(cs47l92_snd_controls), .dapm_widgets = cs47l92_dapm_widgets, diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index d6d4b4121369..2ed3fa67027d 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1909,10 +1909,9 @@ static struct snd_soc_dai_driver wm5102_dai[] = { }, }; -static int wm5102_open(struct snd_compr_stream *stream) +static int wm5102_open(struct snd_soc_component *component, + 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 wm5102_priv *priv = snd_soc_component_get_drvdata(component); return wm_adsp_compr_open(&priv->core.adsp[0], stream); @@ -1992,7 +1991,7 @@ static unsigned int wm5102_digital_vu[] = { ARIZONA_DAC_DIGITAL_VOLUME_5R, }; -static struct snd_compr_ops wm5102_compr_ops = { +static struct snd_compress_ops wm5102_compress_ops = { .open = wm5102_open, .free = wm_adsp_compr_free, .set_params = wm_adsp_compr_set_params, @@ -2008,7 +2007,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm5102 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm5102_set_fll, .name = DRV_NAME, - .compr_ops = &wm5102_compr_ops, + .compress_ops = &wm5102_compress_ops, .controls = wm5102_snd_controls, .num_controls = ARRAY_SIZE(wm5102_snd_controls), .dapm_widgets = wm5102_dapm_widgets, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 499e87d1dfcc..44de44bff423 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2237,10 +2237,10 @@ static struct snd_soc_dai_driver wm5110_dai[] = { }, }; -static int wm5110_open(struct snd_compr_stream *stream) +static int wm5110_open(struct snd_soc_component *component, + 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 wm5110_priv *priv = snd_soc_component_get_drvdata(component); struct arizona *arizona = priv->core.arizona; int n_adsp; @@ -2355,7 +2355,7 @@ static unsigned int wm5110_digital_vu[] = { ARIZONA_DAC_DIGITAL_VOLUME_6R, }; -static struct snd_compr_ops wm5110_compr_ops = { +static struct snd_compress_ops wm5110_compress_ops = { .open = wm5110_open, .free = wm_adsp_compr_free, .set_params = wm_adsp_compr_set_params, @@ -2371,7 +2371,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm5110 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm5110_set_fll, .name = DRV_NAME, - .compr_ops = &wm5110_compr_ops, + .compress_ops = &wm5110_compress_ops, .controls = wm5110_snd_controls, .num_controls = ARRAY_SIZE(wm5110_snd_controls), .dapm_widgets = wm5110_dapm_widgets, diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 1ef69409ccd1..519ca2e69637 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -3509,7 +3509,8 @@ out: } EXPORT_SYMBOL_GPL(wm_adsp_compr_open); -int wm_adsp_compr_free(struct snd_compr_stream *stream) +int wm_adsp_compr_free(struct snd_soc_component *component, + struct snd_compr_stream *stream) { struct wm_adsp_compr *compr = stream->runtime->private_data; struct wm_adsp *dsp = compr->dsp; @@ -3583,7 +3584,8 @@ static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr) return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE; } -int wm_adsp_compr_set_params(struct snd_compr_stream *stream, +int wm_adsp_compr_set_params(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_params *params) { struct wm_adsp_compr *compr = stream->runtime->private_data; @@ -3610,7 +3612,8 @@ int wm_adsp_compr_set_params(struct snd_compr_stream *stream, } EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params); -int wm_adsp_compr_get_caps(struct snd_compr_stream *stream, +int wm_adsp_compr_get_caps(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_caps *caps) { struct wm_adsp_compr *compr = stream->runtime->private_data; @@ -3976,7 +3979,8 @@ static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf) return 0; } -int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd) +int wm_adsp_compr_trigger(struct snd_soc_component *component, + struct snd_compr_stream *stream, int cmd) { struct wm_adsp_compr *compr = stream->runtime->private_data; struct wm_adsp *dsp = compr->dsp; @@ -4139,7 +4143,8 @@ static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf) buf->irq_count); } -int wm_adsp_compr_pointer(struct snd_compr_stream *stream, +int wm_adsp_compr_pointer(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_tstamp *tstamp) { struct wm_adsp_compr *compr = stream->runtime->private_data; @@ -4297,7 +4302,8 @@ static int wm_adsp_compr_read(struct wm_adsp_compr *compr, return ntotal; } -int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf, +int wm_adsp_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *stream, char __user *buf, size_t count) { struct wm_adsp_compr *compr = stream->runtime->private_data; diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 4c481cf20275..1996350b817e 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -190,16 +190,22 @@ int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream); -int wm_adsp_compr_free(struct snd_compr_stream *stream); -int wm_adsp_compr_set_params(struct snd_compr_stream *stream, +int wm_adsp_compr_free(struct snd_soc_component *component, + struct snd_compr_stream *stream); +int wm_adsp_compr_set_params(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_params *params); -int wm_adsp_compr_get_caps(struct snd_compr_stream *stream, +int wm_adsp_compr_get_caps(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_caps *caps); -int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd); +int wm_adsp_compr_trigger(struct snd_soc_component *component, + struct snd_compr_stream *stream, int cmd); int wm_adsp_compr_handle_irq(struct wm_adsp *dsp); -int wm_adsp_compr_pointer(struct snd_compr_stream *stream, +int wm_adsp_compr_pointer(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_tstamp *tstamp); -int wm_adsp_compr_copy(struct snd_compr_stream *stream, +int wm_adsp_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *stream, char __user *buf, size_t count); int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, unsigned int alg, void *buf, size_t len); From 171d1785c703e2f3713a877881412145f6ce98ca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:08:30 +0900 Subject: [PATCH 089/428] ASoC: uniphier: use snd_compress_ops We can use snd_compress_ops. Let's switch to use it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87sggyvdld.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/uniphier/aio-compress.c | 45 ++++++++++++++++++++----------- sound/soc/uniphier/aio-dma.c | 2 +- sound/soc/uniphier/aio.h | 2 +- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/sound/soc/uniphier/aio-compress.c b/sound/soc/uniphier/aio-compress.c index 232d3cc5bce0..0f76bc601ca9 100644 --- a/sound/soc/uniphier/aio-compress.c +++ b/sound/soc/uniphier/aio-compress.c @@ -16,8 +16,10 @@ #include "aio.h" -static int uniphier_aio_compr_prepare(struct snd_compr_stream *cstream); -static int uniphier_aio_compr_hw_free(struct snd_compr_stream *cstream); +static int uniphier_aio_compr_prepare(struct snd_soc_component *component, + struct snd_compr_stream *cstream); +static int uniphier_aio_compr_hw_free(struct snd_soc_component *component, + struct snd_compr_stream *cstream); static int uniphier_aio_comprdma_new(struct snd_soc_pcm_runtime *rtd) { @@ -70,7 +72,8 @@ static int uniphier_aio_comprdma_free(struct snd_soc_pcm_runtime *rtd) return 0; } -static int uniphier_aio_compr_open(struct snd_compr_stream *cstream) +static int uniphier_aio_compr_open(struct snd_soc_component *component, + struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); @@ -95,14 +98,15 @@ static int uniphier_aio_compr_open(struct snd_compr_stream *cstream) return 0; } -static int uniphier_aio_compr_free(struct snd_compr_stream *cstream) +static int uniphier_aio_compr_free(struct snd_soc_component *component, + struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; int ret; - ret = uniphier_aio_compr_hw_free(cstream); + ret = uniphier_aio_compr_hw_free(component, cstream); if (ret) return ret; ret = uniphier_aio_comprdma_free(rtd); @@ -114,7 +118,8 @@ static int uniphier_aio_compr_free(struct snd_compr_stream *cstream) return 0; } -static int uniphier_aio_compr_get_params(struct snd_compr_stream *cstream, +static int uniphier_aio_compr_get_params(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_codec *params) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; @@ -126,7 +131,8 @@ static int uniphier_aio_compr_get_params(struct snd_compr_stream *cstream, return 0; } -static int uniphier_aio_compr_set_params(struct snd_compr_stream *cstream, +static int uniphier_aio_compr_set_params(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_params *params) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; @@ -155,14 +161,15 @@ static int uniphier_aio_compr_set_params(struct snd_compr_stream *cstream, aio_port_reset(sub); aio_src_reset(sub); - ret = uniphier_aio_compr_prepare(cstream); + ret = uniphier_aio_compr_prepare(component, cstream); if (ret) return ret; return 0; } -static int uniphier_aio_compr_hw_free(struct snd_compr_stream *cstream) +static int uniphier_aio_compr_hw_free(struct snd_soc_component *component, + struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); @@ -173,7 +180,8 @@ static int uniphier_aio_compr_hw_free(struct snd_compr_stream *cstream) return 0; } -static int uniphier_aio_compr_prepare(struct snd_compr_stream *cstream) +static int uniphier_aio_compr_prepare(struct snd_soc_component *component, + struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_compr_runtime *runtime = cstream->runtime; @@ -210,7 +218,8 @@ static int uniphier_aio_compr_prepare(struct snd_compr_stream *cstream) return 0; } -static int uniphier_aio_compr_trigger(struct snd_compr_stream *cstream, +static int uniphier_aio_compr_trigger(struct snd_soc_component *component, + struct snd_compr_stream *cstream, int cmd) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; @@ -243,7 +252,8 @@ static int uniphier_aio_compr_trigger(struct snd_compr_stream *cstream, return ret; } -static int uniphier_aio_compr_pointer(struct snd_compr_stream *cstream, +static int uniphier_aio_compr_pointer(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_tstamp *tstamp) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; @@ -316,7 +326,8 @@ static int aio_compr_send_to_hw(struct uniphier_aio_sub *sub, return 0; } -static int uniphier_aio_compr_copy(struct snd_compr_stream *cstream, +static int uniphier_aio_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *cstream, char __user *buf, size_t count) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; @@ -375,7 +386,8 @@ static int uniphier_aio_compr_copy(struct snd_compr_stream *cstream, return cnt; } -static int uniphier_aio_compr_get_caps(struct snd_compr_stream *cstream, +static int uniphier_aio_compr_get_caps(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_caps *caps) { caps->num_codecs = 1; @@ -401,7 +413,8 @@ static const struct snd_compr_codec_caps caps_iec = { .descriptor[0].formats = 0, }; -static int uniphier_aio_compr_get_codec_caps(struct snd_compr_stream *stream, +static int uniphier_aio_compr_get_codec_caps(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_codec_caps *codec) { if (codec->codec == SND_AUDIOCODEC_IEC61937) @@ -412,7 +425,7 @@ static int uniphier_aio_compr_get_codec_caps(struct snd_compr_stream *stream, return 0; } -const struct snd_compr_ops uniphier_aio_compr_ops = { +const struct snd_compress_ops uniphier_aio_compress_ops = { .open = uniphier_aio_compr_open, .free = uniphier_aio_compr_free, .get_params = uniphier_aio_compr_get_params, diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c index 4bbcb007df41..d6bcd476df12 100644 --- a/sound/soc/uniphier/aio-dma.c +++ b/sound/soc/uniphier/aio-dma.c @@ -227,7 +227,7 @@ static const struct snd_soc_component_driver uniphier_soc_platform = { .pointer = uniphier_aiodma_pointer, .mmap = uniphier_aiodma_mmap, .pcm_construct = uniphier_aiodma_new, - .compr_ops = &uniphier_aio_compr_ops, + .compress_ops = &uniphier_aio_compress_ops, }; static const struct regmap_config aiodma_regmap_config = { diff --git a/sound/soc/uniphier/aio.h b/sound/soc/uniphier/aio.h index 694ac030950e..0b03571aa9f0 100644 --- a/sound/soc/uniphier/aio.h +++ b/sound/soc/uniphier/aio.h @@ -304,7 +304,7 @@ static inline struct uniphier_aio *uniphier_priv(struct snd_soc_dai *dai) } int uniphier_aiodma_soc_register_platform(struct platform_device *pdev); -extern const struct snd_compr_ops uniphier_aio_compr_ops; +extern const struct snd_compress_ops uniphier_aio_compress_ops; int uniphier_aio_dai_probe(struct snd_soc_dai *dai); int uniphier_aio_dai_remove(struct snd_soc_dai *dai); From 849db80ef0ba272dbffe2ca5de6f3ffa09b5a76c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:08:44 +0900 Subject: [PATCH 090/428] ASoC: qcom: q6sp6: use snd_compress_ops We can use snd_compress_ops. Let's switch to use it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87r1wivdkz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6asm-dai.c | 51 ++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 125af00bba53..ce77446dbbdd 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -540,19 +540,19 @@ static void compress_event_handler(uint32_t opcode, uint32_t token, } } -static int q6asm_dai_compr_open(struct snd_compr_stream *stream) +static int q6asm_dai_compr_open(struct snd_soc_component *component, + struct snd_compr_stream *stream) { struct snd_soc_pcm_runtime *rtd = stream->private_data; - struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_compr_runtime *runtime = stream->runtime; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct q6asm_dai_data *pdata; - struct device *dev = c->dev; + struct device *dev = component->dev; struct q6asm_dai_rtd *prtd; int stream_id, size, ret; stream_id = cpu_dai->driver->id; - pdata = snd_soc_component_get_drvdata(c); + pdata = snd_soc_component_get_drvdata(component); if (!pdata) { dev_err(dev, "Drv data not found ..\n"); return -EINVAL; @@ -600,7 +600,8 @@ free_prtd: return ret; } -static int q6asm_dai_compr_free(struct snd_compr_stream *stream) +static int q6asm_dai_compr_free(struct snd_soc_component *component, + struct snd_compr_stream *stream) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; @@ -622,13 +623,13 @@ static int q6asm_dai_compr_free(struct snd_compr_stream *stream) return 0; } -static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, +static int q6asm_dai_compr_set_params(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_params *params) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = stream->private_data; - struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); int dir = stream->direction; struct q6asm_dai_data *pdata; struct q6asm_flac_cfg flac_cfg; @@ -636,7 +637,7 @@ static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, struct q6asm_alac_cfg alac_cfg; struct q6asm_ape_cfg ape_cfg; unsigned int wma_v9 = 0; - struct device *dev = c->dev; + struct device *dev = component->dev; int ret; union snd_codec_options *codec_options; struct snd_dec_flac *flac; @@ -649,7 +650,7 @@ static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, memcpy(&prtd->codec_param, params, sizeof(*params)); - pdata = snd_soc_component_get_drvdata(c); + pdata = snd_soc_component_get_drvdata(component); if (!pdata) return -EINVAL; @@ -842,7 +843,8 @@ static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, return 0; } -static int q6asm_dai_compr_trigger(struct snd_compr_stream *stream, int cmd) +static int q6asm_dai_compr_trigger(struct snd_soc_component *component, + struct snd_compr_stream *stream, int cmd) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; @@ -870,8 +872,9 @@ static int q6asm_dai_compr_trigger(struct snd_compr_stream *stream, int cmd) return ret; } -static int q6asm_dai_compr_pointer(struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) +static int q6asm_dai_compr_pointer(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_tstamp *tstamp) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; @@ -887,8 +890,9 @@ static int q6asm_dai_compr_pointer(struct snd_compr_stream *stream, return 0; } -static int q6asm_dai_compr_ack(struct snd_compr_stream *stream, - size_t count) +static int q6asm_dai_compr_ack(struct snd_soc_component *component, + struct snd_compr_stream *stream, + size_t count) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; @@ -901,21 +905,21 @@ static int q6asm_dai_compr_ack(struct snd_compr_stream *stream, return count; } -static int q6asm_dai_compr_mmap(struct snd_compr_stream *stream, - struct vm_area_struct *vma) +static int q6asm_dai_compr_mmap(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct vm_area_struct *vma) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = stream->private_data; - struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); - struct device *dev = c->dev; + struct device *dev = component->dev; return dma_mmap_coherent(dev, vma, prtd->dma_buffer.area, prtd->dma_buffer.addr, prtd->dma_buffer.bytes); } -static int q6asm_dai_compr_get_caps(struct snd_compr_stream *stream, +static int q6asm_dai_compr_get_caps(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_caps *caps) { caps->direction = SND_COMPRESS_PLAYBACK; @@ -933,7 +937,8 @@ static int q6asm_dai_compr_get_caps(struct snd_compr_stream *stream, return 0; } -static int q6asm_dai_compr_get_codec_caps(struct snd_compr_stream *stream, +static int q6asm_dai_compr_get_codec_caps(struct snd_soc_component *component, + struct snd_compr_stream *stream, struct snd_compr_codec_caps *codec) { switch (codec->codec) { @@ -947,7 +952,7 @@ static int q6asm_dai_compr_get_codec_caps(struct snd_compr_stream *stream, return 0; } -static struct snd_compr_ops q6asm_dai_compr_ops = { +static struct snd_compress_ops q6asm_dai_compress_ops = { .open = q6asm_dai_compr_open, .free = q6asm_dai_compr_free, .set_params = q6asm_dai_compr_set_params, @@ -1021,7 +1026,7 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = { .mmap = q6asm_dai_mmap, .pcm_construct = q6asm_dai_pcm_new, .pcm_destruct = q6asm_dai_pcm_free, - .compr_ops = &q6asm_dai_compr_ops, + .compress_ops = &q6asm_dai_compress_ops, }; static struct snd_soc_dai_driver q6asm_fe_dais_template[] = { From c60e4459c42de356b5cc49830fc08e5fd372a8cd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:09:09 +0900 Subject: [PATCH 091/428] ASoC: intel: atom: use snd_compress_ops vWe can use snd_compress_ops. Let's switch to use it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87pnc2vdka.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- .../intel/atom/sst-mfld-platform-compress.c | 43 +++++++++++-------- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +- sound/soc/intel/atom/sst-mfld-platform.h | 2 +- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/atom/sst-mfld-platform-compress.c b/sound/soc/intel/atom/sst-mfld-platform-compress.c index 4a7a9426a3b9..1595e01a7e12 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-compress.c +++ b/sound/soc/intel/atom/sst-mfld-platform-compress.c @@ -39,7 +39,8 @@ static void sst_drain_notify(void *arg) snd_compr_drain_notify(cstream); } -static int sst_platform_compr_open(struct snd_compr_stream *cstream) +static int sst_platform_compr_open(struct snd_soc_component *component, + struct snd_compr_stream *cstream) { int ret_val = 0; @@ -72,7 +73,8 @@ out_ops: return ret_val; } -static int sst_platform_compr_free(struct snd_compr_stream *cstream) +static int sst_platform_compr_free(struct snd_soc_component *component, + struct snd_compr_stream *cstream) { struct sst_runtime_stream *stream; int ret_val = 0, str_id; @@ -91,15 +93,14 @@ static int sst_platform_compr_free(struct snd_compr_stream *cstream) return 0; } -static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, - struct snd_compr_params *params) +static int sst_platform_compr_set_params(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + struct snd_compr_params *params) { struct sst_runtime_stream *stream; int retval; struct snd_sst_params str_params; struct sst_compress_cb cb; - struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct sst_data *ctx = snd_soc_component_get_drvdata(component); stream = cstream->runtime->private_data; @@ -166,7 +167,8 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, return 0; } -static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) +static int sst_platform_compr_trigger(struct snd_soc_component *component, + struct snd_compr_stream *cstream, int cmd) { struct sst_runtime_stream *stream = cstream->runtime->private_data; @@ -199,8 +201,9 @@ static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) return -EINVAL; } -static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) +static int sst_platform_compr_pointer(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) { struct sst_runtime_stream *stream; @@ -212,8 +215,9 @@ static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, return 0; } -static int sst_platform_compr_ack(struct snd_compr_stream *cstream, - size_t bytes) +static int sst_platform_compr_ack(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + size_t bytes) { struct sst_runtime_stream *stream; @@ -224,8 +228,9 @@ static int sst_platform_compr_ack(struct snd_compr_stream *cstream, return 0; } -static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, - struct snd_compr_caps *caps) +static int sst_platform_compr_get_caps(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + struct snd_compr_caps *caps) { struct sst_runtime_stream *stream = cstream->runtime->private_data; @@ -233,8 +238,9 @@ static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, return stream->compr_ops->get_caps(caps); } -static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, - struct snd_compr_codec_caps *codec) +static int sst_platform_compr_get_codec_caps(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + struct snd_compr_codec_caps *codec) { struct sst_runtime_stream *stream = cstream->runtime->private_data; @@ -242,8 +248,9 @@ static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, return stream->compr_ops->get_codec_caps(codec); } -static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream, - struct snd_compr_metadata *metadata) +static int sst_platform_compr_set_metadata(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata) { struct sst_runtime_stream *stream = cstream->runtime->private_data; @@ -251,7 +258,7 @@ static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream, return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata); } -const struct snd_compr_ops sst_platform_compr_ops = { +const struct snd_compress_ops sst_platform_compress_ops = { .open = sst_platform_compr_open, .free = sst_platform_compr_free, diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 82f2b6357778..2e9222ed9daa 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -684,7 +684,7 @@ static const struct snd_soc_component_driver sst_soc_platform_drv = { .open = sst_soc_open, .trigger = sst_soc_trigger, .pointer = sst_soc_pointer, - .compr_ops = &sst_platform_compr_ops, + .compress_ops = &sst_platform_compress_ops, .pcm_construct = sst_soc_pcm_new, }; diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h index fe4749cfa4f5..10c9ecfa7038 100644 --- a/sound/soc/intel/atom/sst-mfld-platform.h +++ b/sound/soc/intel/atom/sst-mfld-platform.h @@ -17,7 +17,7 @@ #include "sst-atom-controls.h" extern struct sst_device *sst; -extern const struct snd_compr_ops sst_platform_compr_ops; +extern const struct snd_compress_ops sst_platform_compress_ops; #define DRV_NAME "sst" From 39118ce50b85496c0d78614474009fb8cbebb857 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:09:48 +0900 Subject: [PATCH 092/428] ASoC: sof: use snd_compress_ops We can use snd_compress_ops. Let's switch to use it. Upstream code doesn't have sof_compressed_ops. This patch assume it is implemented at out-of-tree. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87o8rmvdj7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sof/compress.c | 7 ++++--- sound/soc/sof/compress.h | 7 ++++--- sound/soc/sof/pcm.c | 4 ++-- sound/soc/sof/sof-priv.h | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 7354dc6a49cf..7294451cd67c 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -13,7 +13,7 @@ #include "ops.h" #include "probe.h" -struct snd_compr_ops sof_probe_compressed_ops = { +struct snd_compress_ops sof_probe_compressed_ops = { .copy = sof_probe_compr_copy, }; EXPORT_SYMBOL(sof_probe_compressed_ops); @@ -117,8 +117,9 @@ int sof_probe_compr_pointer(struct snd_compr_stream *cstream, } EXPORT_SYMBOL(sof_probe_compr_pointer); -int sof_probe_compr_copy(struct snd_compr_stream *cstream, - char __user *buf, size_t count) +int sof_probe_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + char __user *buf, size_t count) { struct snd_compr_runtime *rtd = cstream->runtime; unsigned int offset, n; diff --git a/sound/soc/sof/compress.h b/sound/soc/sof/compress.h index 800f163603e1..0386844c0bf5 100644 --- a/sound/soc/sof/compress.h +++ b/sound/soc/sof/compress.h @@ -13,7 +13,7 @@ #include -extern struct snd_compr_ops sof_probe_compressed_ops; +extern struct snd_compress_ops sof_probe_compressed_ops; int sof_probe_compr_open(struct snd_compr_stream *cstream, struct snd_soc_dai *dai); @@ -25,7 +25,8 @@ int sof_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd, struct snd_soc_dai *dai); int sof_probe_compr_pointer(struct snd_compr_stream *cstream, struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai); -int sof_probe_compr_copy(struct snd_compr_stream *cstream, - char __user *buf, size_t count); +int sof_probe_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + char __user *buf, size_t count); #endif diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 47cd741f2a8c..0885826adb6c 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -785,11 +785,11 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->pointer = sof_pcm_pointer; #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) - pd->compr_ops = &sof_compressed_ops; + pd->compress_ops = &sof_compressed_ops; #endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) /* override cops when probe support is enabled */ - pd->compr_ops = &sof_probe_compressed_ops; + pd->compress_ops = &sof_probe_compressed_ops; #endif pd->pcm_construct = sof_pcm_new; pd->ignore_machine = drv_name; diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index a4b297c842df..965b9da696d5 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -522,7 +522,7 @@ void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev); /* * Platform specific ops. */ -extern struct snd_compr_ops sof_compressed_ops; +extern struct snd_compress_ops sof_compressed_ops; /* * DSP Architectures. From 27ecad217c1437761cb4a9e1409d08bd287c18ed Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:10:00 +0900 Subject: [PATCH 093/428] ASoC: sprd: use snd_compress_ops We can use snd_compress_ops. Let's switch to use it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87mu76vdiv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sprd/sprd-pcm-compress.c | 49 ++++++++++++++---------------- sound/soc/sprd/sprd-pcm-dma.c | 2 +- sound/soc/sprd/sprd-pcm-dma.h | 2 +- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/sound/soc/sprd/sprd-pcm-compress.c b/sound/soc/sprd/sprd-pcm-compress.c index 74d48340cade..749dcb7b993b 100644 --- a/sound/soc/sprd/sprd-pcm-compress.c +++ b/sound/soc/sprd/sprd-pcm-compress.c @@ -96,7 +96,8 @@ struct sprd_compr_stream { int stage1_pointer; }; -static int sprd_platform_compr_trigger(struct snd_compr_stream *cstream, +static int sprd_platform_compr_trigger(struct snd_soc_component *component, + struct snd_compr_stream *cstream, int cmd); static void sprd_platform_compr_drain_notify(void *arg) @@ -125,15 +126,14 @@ static void sprd_platform_compr_dma_complete(void *data) snd_compr_fragment_elapsed(cstream); } -static int sprd_platform_compr_dma_config(struct snd_compr_stream *cstream, +static int sprd_platform_compr_dma_config(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_params *params, int channel) { struct snd_compr_runtime *runtime = cstream->runtime; struct sprd_compr_stream *stream = runtime->private_data; struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct device *dev = component->dev; struct sprd_compr_data *data = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct sprd_pcm_dma_params *dma_params = data->dma_params; @@ -261,14 +261,12 @@ sg_err: return ret; } -static int sprd_platform_compr_set_params(struct snd_compr_stream *cstream, +static int sprd_platform_compr_set_params(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_params *params) { struct snd_compr_runtime *runtime = cstream->runtime; struct sprd_compr_stream *stream = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct device *dev = component->dev; struct sprd_compr_params compr_params = { }; int ret; @@ -279,13 +277,13 @@ static int sprd_platform_compr_set_params(struct snd_compr_stream *cstream, * means once the source channel's transaction is done, it will trigger * the destination channel's transaction automatically. */ - ret = sprd_platform_compr_dma_config(cstream, params, 1); + ret = sprd_platform_compr_dma_config(component, cstream, params, 1); if (ret) { dev_err(dev, "failed to config stage 1 DMA: %d\n", ret); return ret; } - ret = sprd_platform_compr_dma_config(cstream, params, 0); + ret = sprd_platform_compr_dma_config(component, cstream, params, 0); if (ret) { dev_err(dev, "failed to config stage 0 DMA: %d\n", ret); goto config_err; @@ -314,12 +312,11 @@ config_err: return ret; } -static int sprd_platform_compr_open(struct snd_compr_stream *cstream) +static int sprd_platform_compr_open(struct snd_soc_component *component, + struct snd_compr_stream *cstream) { struct snd_compr_runtime *runtime = cstream->runtime; struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct device *dev = component->dev; struct sprd_compr_data *data = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct sprd_compr_stream *stream; @@ -392,13 +389,11 @@ err_iram: return ret; } -static int sprd_platform_compr_free(struct snd_compr_stream *cstream) +static int sprd_platform_compr_free(struct snd_soc_component *component, + struct snd_compr_stream *cstream) { struct snd_compr_runtime *runtime = cstream->runtime; struct sprd_compr_stream *stream = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct device *dev = component->dev; int stream_id = cstream->direction, i; @@ -420,14 +415,12 @@ static int sprd_platform_compr_free(struct snd_compr_stream *cstream) return 0; } -static int sprd_platform_compr_trigger(struct snd_compr_stream *cstream, +static int sprd_platform_compr_trigger(struct snd_soc_component *component, + struct snd_compr_stream *cstream, int cmd) { struct snd_compr_runtime *runtime = cstream->runtime; struct sprd_compr_stream *stream = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct device *dev = component->dev; int channels = stream->num_channels, ret = 0, i; int stream_id = cstream->direction; @@ -518,7 +511,8 @@ static int sprd_platform_compr_trigger(struct snd_compr_stream *cstream, return ret; } -static int sprd_platform_compr_pointer(struct snd_compr_stream *cstream, +static int sprd_platform_compr_pointer(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_tstamp *tstamp) { struct snd_compr_runtime *runtime = cstream->runtime; @@ -532,7 +526,8 @@ static int sprd_platform_compr_pointer(struct snd_compr_stream *cstream, return 0; } -static int sprd_platform_compr_copy(struct snd_compr_stream *cstream, +static int sprd_platform_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *cstream, char __user *buf, size_t count) { struct snd_compr_runtime *runtime = cstream->runtime; @@ -609,7 +604,8 @@ copy_done: return count; } -static int sprd_platform_compr_get_caps(struct snd_compr_stream *cstream, +static int sprd_platform_compr_get_caps(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_caps *caps) { caps->direction = cstream->direction; @@ -625,7 +621,8 @@ static int sprd_platform_compr_get_caps(struct snd_compr_stream *cstream, } static int -sprd_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, +sprd_platform_compr_get_codec_caps(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_codec_caps *codec) { switch (codec->codec) { @@ -658,7 +655,7 @@ sprd_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, return 0; } -const struct snd_compr_ops sprd_platform_compr_ops = { +const struct snd_compress_ops sprd_platform_compress_ops = { .open = sprd_platform_compr_open, .free = sprd_platform_compr_free, .set_params = sprd_platform_compr_set_params, diff --git a/sound/soc/sprd/sprd-pcm-dma.c b/sound/soc/sprd/sprd-pcm-dma.c index d12d3cad8cbd..5074123f8855 100644 --- a/sound/soc/sprd/sprd-pcm-dma.c +++ b/sound/soc/sprd/sprd-pcm-dma.c @@ -515,7 +515,7 @@ static const struct snd_soc_component_driver sprd_soc_component = { .mmap = sprd_pcm_mmap, .pcm_construct = sprd_pcm_new, .pcm_destruct = sprd_pcm_free, - .compr_ops = &sprd_platform_compr_ops, + .compress_ops = &sprd_platform_compress_ops, }; static int sprd_soc_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/sprd/sprd-pcm-dma.h b/sound/soc/sprd/sprd-pcm-dma.h index 08e9fdba82f1..be5e385f5e42 100644 --- a/sound/soc/sprd/sprd-pcm-dma.h +++ b/sound/soc/sprd/sprd-pcm-dma.h @@ -6,7 +6,7 @@ #define DRV_NAME "sprd_pcm_dma" #define SPRD_PCM_CHANNEL_MAX 2 -extern const struct snd_compr_ops sprd_platform_compr_ops; +extern const struct snd_compress_ops sprd_platform_compress_ops; struct sprd_pcm_dma_params { dma_addr_t dev_phys[SPRD_PCM_CHANNEL_MAX]; From e7cbe528391ab6660f747095efb6ee1542e4f205 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:10:15 +0900 Subject: [PATCH 094/428] ASoC: soc-compress: remove snd_compr_ops snd_compr_ops couldn't care called component, but now we can care it via snd_compress_ops. All drivers switched to it. This patch removes snd_compr_ops. Signed-off-by: Kuninori Morimoto Tested-by: Charles Keepax Reviewed-by: Charles Keepax Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87lfmqvdig.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 - sound/soc/soc-compress.c | 145 ---------------------------------- 2 files changed, 146 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 9122b11f51e9..864983b09846 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -146,7 +146,6 @@ struct snd_soc_component_driver { struct snd_pcm_substream *substream, struct vm_area_struct *vma); - const struct snd_compr_ops *compr_ops; /* remove me */ const struct snd_compress_ops *compress_ops; /* probe ordering - for components with runtime dependencies */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 343de969179e..ceaf976db0bb 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -44,23 +44,6 @@ static int soc_compr_components_open(struct snd_compr_stream *cstream, } } - /* remvoe me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->open) - continue; - - ret = component->driver->compr_ops->open(cstream); - if (ret < 0) { - dev_err(component->dev, - "Compress ASoC: can't open platform %s: %d\n", - component->name, ret); - - *last = component; - return ret; - } - } - *last = NULL; return 0; } @@ -83,18 +66,6 @@ static int soc_compr_components_free(struct snd_compr_stream *cstream, component->driver->compress_ops->free(component, cstream); } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (component == last) - break; - - if (!component->driver->compr_ops || - !component->driver->compr_ops->free) - continue; - - component->driver->compr_ops->free(cstream); - } - return 0; } @@ -367,17 +338,6 @@ static int soc_compr_components_trigger(struct snd_compr_stream *cstream, return ret; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->trigger) - continue; - - ret = component->driver->compr_ops->trigger(cstream, cmd); - if (ret < 0) - return ret; - } - return 0; } @@ -481,17 +441,6 @@ static int soc_compr_components_set_params(struct snd_compr_stream *cstream, return ret; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->set_params) - continue; - - ret = component->driver->compr_ops->set_params(cstream, params); - if (ret < 0) - return ret; - } - return 0; } @@ -632,16 +581,6 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->get_params) - continue; - - ret = component->driver->compr_ops->get_params(cstream, params); - break; - } - err: mutex_unlock(&rtd->card->pcm_mutex); return ret; @@ -666,16 +605,6 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->get_caps) - continue; - - ret = component->driver->compr_ops->get_caps(cstream, caps); - break; - } - mutex_unlock(&rtd->card->pcm_mutex); return ret; } @@ -699,17 +628,6 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->get_codec_caps) - continue; - - ret = component->driver->compr_ops->get_codec_caps(cstream, - codec); - break; - } - mutex_unlock(&rtd->card->pcm_mutex); return ret; } @@ -740,17 +658,6 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) goto err; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->ack) - continue; - - ret = component->driver->compr_ops->ack(cstream, bytes); - if (ret < 0) - goto err; - } - err: mutex_unlock(&rtd->card->pcm_mutex); return ret; @@ -779,16 +686,6 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->pointer) - continue; - - ret = component->driver->compr_ops->pointer(cstream, tstamp); - break; - } - mutex_unlock(&rtd->card->pcm_mutex); return ret; } @@ -812,16 +709,6 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->copy) - continue; - - ret = component->driver->compr_ops->copy(cstream, buf, count); - break; - } - mutex_unlock(&rtd->card->pcm_mutex); return ret; } @@ -851,18 +738,6 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream, return ret; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->set_metadata) - continue; - - ret = component->driver->compr_ops->set_metadata(cstream, - metadata); - if (ret < 0) - return ret; - } - return 0; } @@ -889,16 +764,6 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, component, cstream, metadata); } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->get_metadata) - continue; - - return component->driver->compr_ops->get_metadata(cstream, - metadata); - } - return 0; } @@ -1029,16 +894,6 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->copy) - continue; - - compr->ops->copy = soc_compr_copy; - break; - } - mutex_init(&compr->lock); ret = snd_compress_new(rtd->card->snd_card, num, direction, new_name, compr); From 19f303caf63693502cf34897ade76202afe5f445 Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Fri, 17 Apr 2020 18:13:40 -0400 Subject: [PATCH 095/428] dt-bindings: sound: add Microsemi ZL38060 binding Add devicetree binding for the Microsemi ZL38060 Connected Home Audio Processor. Signed-off-by: Sven Van Asbroeck Link: https://lore.kernel.org/r/20200417221341.31428-1-TheSven73@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/zl38060.yaml | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/zl38060.yaml diff --git a/Documentation/devicetree/bindings/sound/zl38060.yaml b/Documentation/devicetree/bindings/sound/zl38060.yaml new file mode 100644 index 000000000000..338e2a13c775 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/zl38060.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/zl38060.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ZL38060 Connected Home Audio Processor from Microsemi. + +description: | + The ZL38060 is a "Connected Home Audio Processor" from Microsemi, + which consists of a Digital Signal Processor (DSP), several Digital + Audio Interfaces (DAIs), analog outputs, and a block of 14 GPIOs. + +maintainers: + - Jaroslav Kysela + - Takashi Iwai + +properties: + compatible: + const: mscc,zl38060 + + reg: + description: + SPI device address. + maxItems: 1 + + spi-max-frequency: + maximum: 24000000 + + reset-gpios: + description: + A GPIO line handling reset of the chip. As the line is active low, + it should be marked GPIO_ACTIVE_LOW (see ../gpio/gpio.txt) + maxItems: 1 + + '#gpio-cells': + const: 2 + + gpio-controller: true + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + - '#gpio-cells' + - gpio-controller + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + #include + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + codec: zl38060@0 { + gpio-controller; + #gpio-cells = <2>; + #sound-dai-cells = <0>; + compatible = "mscc,zl38060"; + reg = <0>; + spi-max-frequency = <12000000>; + reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + }; + }; From 52e8a94baf9026276fcdc9ff21a50dc2ca0bc94b Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Fri, 17 Apr 2020 18:13:41 -0400 Subject: [PATCH 096/428] ASoC: Add initial ZL38060 driver The ZL38060 is a "Connected Home Audio Processor" from Microsemi, which consists of a Digital Signal Processor (DSP), several Digital Audio Interfaces (DAIs), analog outputs, and a block of 14 GPIOs. This driver supports only a tiny subset of the chip's functionality and possible configurations: - bypass mode (whole dsp block is bypassed) - chip's I2S DAI routed directly to/from DACs and microphone - chip's internal clock is driven by a 12 MHz external crystal - chip's DAI connected to CPU is I2S, and bit + frame clock master - chip must be strapped for "host boot": in this mode, firmware will be provided by this driver. Signed-off-by: Sven Van Asbroeck Link: https://lore.kernel.org/r/20200417221341.31428-2-TheSven73@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 11 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/zl38060.c | 638 +++++++++++++++++++++++++++++++++++++ 3 files changed, 651 insertions(+) create mode 100644 sound/soc/codecs/zl38060.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index d0fec1b90256..81341c70d563 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -272,6 +272,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_WM9712 imply SND_SOC_WM9713 imply SND_SOC_WSA881X + imply SND_SOC_ZL38060 help Normally ASoC codec drivers are only built if a machine driver which uses them is also built since they are only usable with a machine @@ -1645,6 +1646,16 @@ config SND_SOC_WSA881X This enables support for Qualcomm WSA8810/WSA8815 Class-D Smart Speaker Amplifier. +config SND_SOC_ZL38060 + tristate "Microsemi ZL38060 Connected Home Audio Processor" + depends on SPI_MASTER + select GPIOLIB + select REGMAP + help + Support for ZL38060 Connected Home Audio Processor from Microsemi, + which consists of a Digital Signal Processor (DSP), several Digital + Audio Interfaces (DAIs), analog outputs, and a block of 14 GPIOs. + config SND_SOC_ZX_AUD96P22 tristate "ZTE ZX AUD96P22 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 03533157cda6..a603532c7af5 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -288,6 +288,7 @@ snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o snd-soc-wm-hubs-objs := wm_hubs.o snd-soc-wsa881x-objs := wsa881x.o +snd-soc-zl38060-objs := zl38060.o snd-soc-zx-aud96p22-objs := zx_aud96p22.o # Amp snd-soc-max9877-objs := max9877.o @@ -588,6 +589,7 @@ obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o +obj-$(CONFIG_SND_SOC_ZL38060) += snd-soc-zl38060.o obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o # Amp diff --git a/sound/soc/codecs/zl38060.c b/sound/soc/codecs/zl38060.c new file mode 100644 index 000000000000..927ad849ad2d --- /dev/null +++ b/sound/soc/codecs/zl38060.c @@ -0,0 +1,638 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Codec driver for Microsemi ZL38060 Connected Home Audio Processor. +// +// Copyright(c) 2020 Sven Van Asbroeck + +// The ZL38060 is very flexible and configurable. This driver implements only a +// tiny subset of the chip's possible configurations: +// +// - DSP block bypassed: DAI routed straight to DACs +// microphone routed straight to DAI +// - chip's internal clock is driven by a 12 MHz external crystal +// - chip's DAI connected to CPU is I2S, and bit + frame clock master +// - chip must be strapped for "host boot": in this mode, firmware will be +// provided by this driver. + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DRV_NAME "zl38060" + +#define ZL38_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_48000) +#define ZL38_FORMATS SNDRV_PCM_FMTBIT_S16_LE + +#define HBI_FIRMWARE_PAGE 0xFF +#define ZL38_MAX_RAW_XFER 0x100 + +#define REG_TDMA_CFG_CLK 0x0262 +#define CFG_CLK_PCLK_SHIFT 4 +#define CFG_CLK_PCLK_MASK (0x7ff << CFG_CLK_PCLK_SHIFT) +#define CFG_CLK_PCLK(bits) ((bits - 1) << CFG_CLK_PCLK_SHIFT) +#define CFG_CLK_MASTER BIT(15) +#define CFG_CLK_FSRATE_MASK 0x7 +#define CFG_CLK_FSRATE_8KHZ 0x1 +#define CFG_CLK_FSRATE_16KHZ 0x2 +#define CFG_CLK_FSRATE_48KHZ 0x6 + +#define REG_CLK_CFG 0x0016 +#define CLK_CFG_SOURCE_XTAL BIT(15) + +#define REG_CLK_STATUS 0x0014 +#define CLK_STATUS_HWRST BIT(0) + +#define REG_PARAM_RESULT 0x0034 +#define PARAM_RESULT_READY 0xD3D3 + +#define REG_PG255_BASE_HI 0x000C +#define REG_PG255_OFFS(addr) ((HBI_FIRMWARE_PAGE << 8) | (addr & 0xFF)) +#define REG_FWR_EXEC 0x012C + +#define REG_CMD 0x0032 +#define REG_HW_REV 0x0020 +#define REG_FW_PROD 0x0022 +#define REG_FW_REV 0x0024 + +#define REG_SEMA_FLAGS 0x0006 +#define SEMA_FLAGS_BOOT_CMD BIT(0) +#define SEMA_FLAGS_APP_REBOOT BIT(1) + +#define REG_HW_REV 0x0020 +#define REG_FW_PROD 0x0022 +#define REG_FW_REV 0x0024 +#define REG_GPIO_DIR 0x02DC +#define REG_GPIO_DAT 0x02DA + +#define BOOTCMD_LOAD_COMPLETE 0x000D +#define BOOTCMD_FW_GO 0x0008 + +#define FIRMWARE_MAJOR 2 +#define FIRMWARE_MINOR 2 + +struct zl38_codec_priv { + struct device *dev; + struct regmap *regmap; + bool is_stream_in_use[2]; + struct gpio_chip *gpio_chip; +}; + +static int zl38_fw_issue_command(struct regmap *regmap, u16 cmd) +{ + unsigned int val; + int err; + + err = regmap_read_poll_timeout(regmap, REG_SEMA_FLAGS, val, + !(val & SEMA_FLAGS_BOOT_CMD), 10000, + 10000 * 100); + if (err) + return err; + err = regmap_write(regmap, REG_CMD, cmd); + if (err) + return err; + err = regmap_update_bits(regmap, REG_SEMA_FLAGS, SEMA_FLAGS_BOOT_CMD, + SEMA_FLAGS_BOOT_CMD); + if (err) + return err; + + return regmap_read_poll_timeout(regmap, REG_CMD, val, !val, 10000, + 10000 * 100); +} + +static int zl38_fw_go(struct regmap *regmap) +{ + int err; + + err = zl38_fw_issue_command(regmap, BOOTCMD_LOAD_COMPLETE); + if (err) + return err; + + return zl38_fw_issue_command(regmap, BOOTCMD_FW_GO); +} + +static int zl38_fw_enter_boot_mode(struct regmap *regmap) +{ + unsigned int val; + int err; + + err = regmap_update_bits(regmap, REG_CLK_STATUS, CLK_STATUS_HWRST, + CLK_STATUS_HWRST); + if (err) + return err; + + return regmap_read_poll_timeout(regmap, REG_PARAM_RESULT, val, + val == PARAM_RESULT_READY, 1000, 50000); +} + +static int +zl38_fw_send_data(struct regmap *regmap, u32 addr, const void *data, u16 len) +{ + __be32 addr_base = cpu_to_be32(addr & ~0xFF); + int err; + + err = regmap_raw_write(regmap, REG_PG255_BASE_HI, &addr_base, + sizeof(addr_base)); + if (err) + return err; + return regmap_raw_write(regmap, REG_PG255_OFFS(addr), data, len); +} + +static int zl38_fw_send_xaddr(struct regmap *regmap, const void *data) +{ + /* execution address from ihex: 32-bit little endian. + * device register expects 32-bit big endian. + */ + u32 addr = le32_to_cpup(data); + __be32 baddr = cpu_to_be32(addr); + + return regmap_raw_write(regmap, REG_FWR_EXEC, &baddr, sizeof(baddr)); +} + +static int zl38_load_firmware(struct device *dev, struct regmap *regmap) +{ + const struct ihex_binrec *rec; + const struct firmware *fw; + u32 addr; + u16 len; + int err; + + /* how to get this firmware: + * 1. request and download chip firmware from Microsemi + * (provided by Microsemi in srec format) + * 2. convert downloaded firmware from srec to ihex. Simple tool: + * https://gitlab.com/TheSven73/s3-to-irec + * 3. convert ihex to binary (.fw) using ihex2fw tool which is included + * with the Linux kernel sources + */ + err = request_ihex_firmware(&fw, "zl38060.fw", dev); + if (err) + return err; + err = zl38_fw_enter_boot_mode(regmap); + if (err) + goto out; + rec = (const struct ihex_binrec *)fw->data; + while (rec) { + addr = be32_to_cpu(rec->addr); + len = be16_to_cpu(rec->len); + if (addr) { + /* regular data ihex record */ + err = zl38_fw_send_data(regmap, addr, rec->data, len); + } else if (len == 4) { + /* execution address ihex record */ + err = zl38_fw_send_xaddr(regmap, rec->data); + } else { + err = -EINVAL; + } + if (err) + goto out; + /* next ! */ + rec = ihex_next_binrec(rec); + } + err = zl38_fw_go(regmap); + +out: + release_firmware(fw); + return err; +} + + +static int zl38_software_reset(struct regmap *regmap) +{ + unsigned int val; + int err; + + err = regmap_update_bits(regmap, REG_SEMA_FLAGS, SEMA_FLAGS_APP_REBOOT, + SEMA_FLAGS_APP_REBOOT); + if (err) + return err; + + /* wait for host bus interface to settle. + * Not sure if this is required: Microsemi's vendor driver does this, + * but the firmware manual does not mention it. Leave it in, there's + * little downside, apart from a slower reset. + */ + msleep(50); + + return regmap_read_poll_timeout(regmap, REG_SEMA_FLAGS, val, + !(val & SEMA_FLAGS_APP_REBOOT), 10000, + 10000 * 100); +} + +static int zl38_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct zl38_codec_priv *priv = snd_soc_dai_get_drvdata(dai); + int err; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + /* firmware default is normal i2s */ + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + /* firmware default is normal bitclock and frame */ + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + /* always 32 bits per frame (= 16 bits/channel, 2 channels) */ + err = regmap_update_bits(priv->regmap, REG_TDMA_CFG_CLK, + CFG_CLK_MASTER | CFG_CLK_PCLK_MASK, + CFG_CLK_MASTER | CFG_CLK_PCLK(32)); + if (err) + return err; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int zl38_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct zl38_codec_priv *priv = snd_soc_dai_get_drvdata(dai); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + unsigned int fsrate; + int err; + + /* We cannot change hw_params while the dai is already in use - the + * software reset will corrupt the audio. However, this is not required, + * as the chip's TDM buses are fully symmetric, which mandates identical + * rates, channels, and samplebits for record and playback. + */ + if (priv->is_stream_in_use[!tx]) + goto skip_setup; + + switch (params_rate(params)) { + case 8000: + fsrate = CFG_CLK_FSRATE_8KHZ; + break; + case 16000: + fsrate = CFG_CLK_FSRATE_16KHZ; + break; + case 48000: + fsrate = CFG_CLK_FSRATE_48KHZ; + break; + default: + return -EINVAL; + }; + + err = regmap_update_bits(priv->regmap, REG_TDMA_CFG_CLK, + CFG_CLK_FSRATE_MASK, fsrate); + if (err) + return err; + + /* chip requires a software reset to apply audio register changes */ + err = zl38_software_reset(priv->regmap); + if (err) + return err; + +skip_setup: + priv->is_stream_in_use[tx] = true; + + return 0; +} + +static int zl38_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct zl38_codec_priv *priv = snd_soc_dai_get_drvdata(dai); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + + priv->is_stream_in_use[tx] = false; + + return 0; +} + +/* stereo bypass with no AEC */ +static const struct reg_sequence cp_config_stereo_bypass[] = { + /* interconnects must be programmed first */ + { 0x0210, 0x0005 }, /* DAC1 in <= I2S1-L */ + { 0x0212, 0x0006 }, /* DAC2 in <= I2S1-R */ + { 0x0214, 0x0001 }, /* I2S1-L in <= MIC1 */ + { 0x0216, 0x0001 }, /* I2S1-R in <= MIC1 */ + { 0x0224, 0x0000 }, /* AEC-S in <= n/a */ + { 0x0226, 0x0000 }, /* AEC-R in <= n/a */ + /* output enables must be programmed next */ + { 0x0202, 0x000F }, /* enable I2S1 + DAC */ +}; + +static const struct snd_soc_dai_ops zl38_dai_ops = { + .set_fmt = zl38_set_fmt, + .hw_params = zl38_hw_params, + .hw_free = zl38_hw_free, +}; + +static struct snd_soc_dai_driver zl38_dai = { + .name = "zl38060-tdma", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ZL38_RATES, + .formats = ZL38_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = ZL38_RATES, + .formats = ZL38_FORMATS, + }, + .ops = &zl38_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + .symmetric_channels = 1, +}; + +static const struct snd_soc_dapm_widget zl38_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("DAC1"), + SND_SOC_DAPM_OUTPUT("DAC2"), + + SND_SOC_DAPM_INPUT("DMICL"), +}; + +static const struct snd_soc_dapm_route zl38_dapm_routes[] = { + { "DAC1", NULL, "Playback" }, + { "DAC2", NULL, "Playback" }, + + { "Capture", NULL, "DMICL" }, +}; + +static const struct snd_soc_component_driver zl38_component_dev = { + .dapm_widgets = zl38_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(zl38_dapm_widgets), + .dapm_routes = zl38_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(zl38_dapm_routes), + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static void chip_gpio_set(struct gpio_chip *c, unsigned int offset, int val) +{ + struct regmap *regmap = gpiochip_get_data(c); + unsigned int mask = BIT(offset); + + regmap_update_bits(regmap, REG_GPIO_DAT, mask, val ? mask : 0); +} + +static int chip_gpio_get(struct gpio_chip *c, unsigned int offset) +{ + struct regmap *regmap = gpiochip_get_data(c); + unsigned int mask = BIT(offset); + unsigned int val; + int err; + + err = regmap_read(regmap, REG_GPIO_DAT, &val); + if (err) + return err; + + return !!(val & mask); +} + +static int chip_direction_input(struct gpio_chip *c, unsigned int offset) +{ + struct regmap *regmap = gpiochip_get_data(c); + unsigned int mask = BIT(offset); + + return regmap_update_bits(regmap, REG_GPIO_DIR, mask, 0); +} + +static int +chip_direction_output(struct gpio_chip *c, unsigned int offset, int val) +{ + struct regmap *regmap = gpiochip_get_data(c); + unsigned int mask = BIT(offset); + + chip_gpio_set(c, offset, val); + return regmap_update_bits(regmap, REG_GPIO_DIR, mask, mask); +} + +static const struct gpio_chip template_chip = { + .owner = THIS_MODULE, + .label = DRV_NAME, + + .base = -1, + .ngpio = 14, + .direction_input = chip_direction_input, + .direction_output = chip_direction_output, + .get = chip_gpio_get, + .set = chip_gpio_set, + + .can_sleep = true, +}; + +static int zl38_check_revision(struct device *dev, struct regmap *regmap) +{ + unsigned int hwrev, fwprod, fwrev; + int fw_major, fw_minor, fw_micro; + int err; + + err = regmap_read(regmap, REG_HW_REV, &hwrev); + if (err) + return err; + err = regmap_read(regmap, REG_FW_PROD, &fwprod); + if (err) + return err; + err = regmap_read(regmap, REG_FW_REV, &fwrev); + if (err) + return err; + + fw_major = (fwrev >> 12) & 0xF; + fw_minor = (fwrev >> 8) & 0xF; + fw_micro = fwrev & 0xFF; + dev_info(dev, "hw rev 0x%x, fw product code %d, firmware rev %d.%d.%d", + hwrev & 0x1F, fwprod, fw_major, fw_minor, fw_micro); + + if (fw_major != FIRMWARE_MAJOR || fw_minor < FIRMWARE_MINOR) { + dev_err(dev, "unsupported firmware. driver supports %d.%d", + FIRMWARE_MAJOR, FIRMWARE_MINOR); + return -EINVAL; + } + + return 0; +} + +static int zl38_bus_read(void *context, + const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_size) +{ + struct spi_device *spi = context; + const u8 *reg_buf8 = reg_buf; + size_t len = 0; + u8 offs, page; + u8 txbuf[4]; + + if (reg_size != 2 || val_size > ZL38_MAX_RAW_XFER) + return -EINVAL; + + offs = reg_buf8[1] >> 1; + page = reg_buf8[0]; + + if (page) { + txbuf[len++] = 0xFE; + txbuf[len++] = page == HBI_FIRMWARE_PAGE ? 0xFF : page - 1; + txbuf[len++] = offs; + txbuf[len++] = val_size / 2 - 1; + } else { + txbuf[len++] = offs | 0x80; + txbuf[len++] = val_size / 2 - 1; + } + + return spi_write_then_read(spi, txbuf, len, val_buf, val_size); +} + +static int zl38_bus_write(void *context, const void *data, size_t count) +{ + struct spi_device *spi = context; + u8 buf[4 + ZL38_MAX_RAW_XFER]; + size_t val_len, len = 0; + const u8 *data8 = data; + u8 offs, page; + + if (count > (2 + ZL38_MAX_RAW_XFER) || count < 4) + return -EINVAL; + val_len = count - 2; + offs = data8[1] >> 1; + page = data8[0]; + + if (page) { + buf[len++] = 0xFE; + buf[len++] = page == HBI_FIRMWARE_PAGE ? 0xFF : page - 1; + buf[len++] = offs; + buf[len++] = (val_len / 2 - 1) | 0x80; + } else { + buf[len++] = offs | 0x80; + buf[len++] = (val_len / 2 - 1) | 0x80; + } + memcpy(buf + len, data8 + 2, val_len); + len += val_len; + + return spi_write(spi, buf, len); +} + +static const struct regmap_bus zl38_regmap_bus = { + .read = zl38_bus_read, + .write = zl38_bus_write, + .max_raw_write = ZL38_MAX_RAW_XFER, + .max_raw_read = ZL38_MAX_RAW_XFER, +}; + +static const struct regmap_config zl38_regmap_conf = { + .reg_bits = 16, + .val_bits = 16, + .reg_stride = 2, + .use_single_read = true, + .use_single_write = true, +}; + +static int zl38_spi_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct zl38_codec_priv *priv; + struct gpio_desc *reset_gpio; + int err; + + /* get the chip to a known state by putting it in reset */ + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return PTR_ERR(reset_gpio); + if (reset_gpio) { + /* datasheet: need > 10us for a digital + analog reset */ + usleep_range(15, 50); + /* take the chip out of reset */ + gpiod_set_value_cansleep(reset_gpio, 0); + /* datasheet: need > 3ms for digital section to become stable */ + usleep_range(3000, 10000); + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + dev_set_drvdata(dev, priv); + priv->regmap = devm_regmap_init(dev, &zl38_regmap_bus, spi, + &zl38_regmap_conf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + err = zl38_load_firmware(dev, priv->regmap); + if (err) + return err; + + err = zl38_check_revision(dev, priv->regmap); + if (err) + return err; + + priv->gpio_chip = devm_kmemdup(dev, &template_chip, + sizeof(template_chip), GFP_KERNEL); + if (!priv->gpio_chip) + return -ENOMEM; +#ifdef CONFIG_OF_GPIO + priv->gpio_chip->of_node = dev->of_node; +#endif + err = devm_gpiochip_add_data(dev, priv->gpio_chip, priv->regmap); + if (err) + return err; + + /* setup the cross-point switch for stereo bypass */ + err = regmap_multi_reg_write(priv->regmap, cp_config_stereo_bypass, + ARRAY_SIZE(cp_config_stereo_bypass)); + if (err) + return err; + /* setup for 12MHz crystal connected to the chip */ + err = regmap_update_bits(priv->regmap, REG_CLK_CFG, CLK_CFG_SOURCE_XTAL, + CLK_CFG_SOURCE_XTAL); + if (err) + return err; + + return devm_snd_soc_register_component(dev, &zl38_component_dev, + &zl38_dai, 1); +} + +static const struct of_device_id zl38_dt_ids[] = { + { .compatible = "mscc,zl38060", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, zl38_dt_ids); + +static const struct spi_device_id zl38_spi_ids[] = { + { "zl38060", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, zl38_spi_ids); + +static struct spi_driver zl38060_spi_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(zl38_dt_ids), + }, + .probe = zl38_spi_probe, + .id_table = zl38_spi_ids, +}; +module_spi_driver(zl38060_spi_driver); + +MODULE_DESCRIPTION("ASoC ZL38060 driver"); +MODULE_AUTHOR("Sven Van Asbroeck "); +MODULE_LICENSE("GPL v2"); From 5bf73b1b1deca46c7459cb4d732ba8bad6da93c5 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 20 Apr 2020 23:54:31 +0300 Subject: [PATCH 097/428] ASoC: intel/skl/hda - fix oops on systems without i915 audio codec Recent fix for jack detection caused a regression on systems with HDA audio codec but no HDMI/DP audio via i915 graphics, leading to a kernel oops at device probe. On these systems, HDA bus instance lookup fails, as the first ASoC runtime of the card is connected to a dummy codec (as no HDMI codec is present). Fixes: 3a24f135e6cc ("ASoC: intel/skl/hda - set autosuspend timeout for hda codecs") Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200420205431.13070-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_generic.c | 32 +++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 35f222ed9912..fc9290fb4e99 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -172,23 +172,25 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card) { - struct snd_soc_pcm_runtime *rtd = - list_first_entry(&card->rtd_list, - struct snd_soc_pcm_runtime, list); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_pcm_runtime *rtd; struct hdac_hda_priv *hda_pvt; + struct snd_soc_dai *dai; - if (!codec_dai) - return; - - /* - * all codecs are on the same bus, so it's sufficient - * to lookup the first runtime and its codec, and set - * power save defaults for all codecs on the bus - */ - hda_pvt = snd_soc_component_get_drvdata(codec_dai->component); - snd_hda_set_power_save(hda_pvt->codec.bus, - HDA_CODEC_AUTOSUSPEND_DELAY_MS); + for_each_card_rtds(card, rtd) { + if (!strstr(rtd->dai_link->codecs->name, "ehdaudio")) + continue; + dai = asoc_rtd_to_codec(rtd, 0); + hda_pvt = snd_soc_component_get_drvdata(dai->component); + if (hda_pvt) { + /* + * all codecs are on the same bus, so it's sufficient + * to look up only the first one + */ + snd_hda_set_power_save(hda_pvt->codec.bus, + HDA_CODEC_AUTOSUSPEND_DELAY_MS); + break; + } + } } static int skl_hda_audio_probe(struct platform_device *pdev) From 8137d2763bf77d68babb38a7323c5152c945f20e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 22 Apr 2020 12:22:55 +0300 Subject: [PATCH 098/428] ALSA: usb-audio: Fix a limit check in proc_dump_substream_formats() This should be ARRAY_SIZE() instead of sizeof(). The sizeof() limit is too high so it doesn't work. Fixes: 093b8494f299 ("ALSA: usb-audio: Print more information in stream proc files") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20200422092255.GB195357@mwanda Signed-off-by: Takashi Iwai --- sound/usb/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index 5a36e192ebb0..889c550c9f29 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -140,7 +140,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s snd_iprintf(buffer, " Channel map:"); for (c = 0; c < map->channels; c++) { - if (map->map[c] >= sizeof(channel_labels) || + if (map->map[c] >= ARRAY_SIZE(channel_labels) || !channel_labels[map->map[c]]) snd_iprintf(buffer, " --"); else From 14ff6c5546e7d98f8326d9ee7a75b79de9874efb Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Wed, 22 Apr 2020 15:16:46 +0800 Subject: [PATCH 099/428] ALSA: oxygen: use true,false for bool variables Fix the following coccicheck warning: sound/pci/oxygen/xonar_pcm179x.c:463:1-17: WARNING: Assignment of 0/1 to bool variable sound/pci/oxygen/xonar_pcm179x.c:505:1-17: WARNING: Assignment of 0/1 to bool variable Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200422071646.48436-1-yanaijie@huawei.com Signed-off-by: Takashi Iwai --- sound/pci/oxygen/xonar_pcm179x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index 6a0520c4fb5a..cf801a235df9 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c @@ -460,7 +460,7 @@ static void xonar_st_init(struct oxygen *chip) data->generic.anti_pop_delay = 100; data->h6 = chip->model.dac_channels_mixer > 2; - data->has_cs2000 = 1; + data->has_cs2000 = true; data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; data->broken_i2c = true; @@ -502,7 +502,7 @@ static void xonar_xense_init(struct oxygen *chip) xonar_init_ext_power(chip); data->generic.anti_pop_delay = 100; - data->has_cs2000 = 1; + data->has_cs2000 = true; data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, From d8e25a10ef876bfb2e6ee611fbbb7f7c926a3309 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 22 Apr 2020 12:07:10 +0100 Subject: [PATCH 100/428] ASoC: SOF: Fix build The recent batch of SOF changes failed to build on some x86 configurations including an allmodconfig, revert the commits: e150ef4169a76 ASoC: SOF: Introduce extended manifest 371091417864b ASoC: SOF: ext_manifest: parse firmware version 7c024b948c206 ASoC: SOF: ext_manifest: parse compiler version 9e72f13ee541c ASoC: SOF: ext_manifest: parse windows to fix this. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 91 ------------- sound/soc/sof/loader.c | 189 +------------------------- 2 files changed, 2 insertions(+), 278 deletions(-) delete mode 100644 include/uapi/sound/sof/ext_manifest.h diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h deleted file mode 100644 index d49c47d08c7f..000000000000 --- a/include/uapi/sound/sof/ext_manifest.h +++ /dev/null @@ -1,91 +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) 2020 Intel Corporation. All rights reserved. - */ - -/* - * Extended manifest is a place to store metadata about firmware, known during - * compilation time - for example firmware version or used compiler. - * Given information are read on host side before firmware startup. - * This part of output binary is not signed. - */ - -#ifndef __SOF_FIRMWARE_EXT_MANIFEST_H__ -#define __SOF_FIRMWARE_EXT_MANIFEST_H__ - -#include -#include - -/* In ASCII `XMan` */ -#define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 - -/* Build u32 number in format MMmmmppp */ -#define SOF_EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ((uint32_t)( \ - ((MAJOR) << 24) | \ - ((MINOR) << 12) | \ - (PATH))) - -/* check extended manifest version consistency */ -#define SOF_EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ - ((host_ver) & GENMASK(31, 24)) != \ - ((cli_ver) & GENMASK(31, 24))) - -/* used extended manifest header version */ -#define SOF_EXT_MAN_VERSION SOF_EXT_MAN_BUILD_VERSION(1, 0, 0) - -/* extended manifest header, deleting any field breaks backward compatibility */ -struct sof_ext_man_header { - uint32_t magic; /*< identification number, */ - /*< EXT_MAN_MAGIC_NUMBER */ - uint32_t full_size; /*< [bytes] full size of ext_man, */ - /*< (header + content + padding) */ - uint32_t header_size; /*< [bytes] makes header extensionable, */ - /*< after append new field to ext_man header */ - /*< then backward compatible won't be lost */ - uint32_t header_version; /*< value of EXT_MAN_VERSION */ - /*< not related with following content */ - uint8_t elements[]; /*< list of ext_man_elem_* elements */ -} __packed; - -/* Now define extended manifest elements */ - -/* Extended manifest elements types */ -enum sof_ext_man_elem_type { - SOF_EXT_MAN_ELEM_FW_VERSION = 0, - SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, - SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, -}; - -/* extended manifest element header */ -struct sof_ext_man_elem_header { - uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ - uint32_t size; /*< in bytes, including header size */ - uint8_t blob[]; /*< type dependent content */ -} __packed; - -/* FW version */ -struct sof_ext_man_fw_version { - struct sof_ext_man_elem_header hdr; - /* use sof_ipc struct because of code re-use */ - struct sof_ipc_fw_version version; - uint32_t flags; -} __packed; - -/* extended data memory windows for IPC, trace and debug */ -struct sof_ext_man_window { - struct sof_ext_man_elem_header hdr; - /* use sof_ipc struct because of code re-use */ - struct sof_ipc_window ipc_window; -} __packed; - -/* Used C compiler description */ -struct sof_ext_man_cc_version { - struct sof_ext_man_elem_header hdr; - /* use sof_ipc struct because of code re-use */ - struct sof_ipc_cc_version cc_version; -} __packed; - -#endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 8be30cd5e038..89f35db2577d 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -12,7 +12,6 @@ #include #include -#include #include "ops.h" static int get_ext_windows(struct snd_sof_dev *sdev, @@ -20,21 +19,13 @@ static int get_ext_windows(struct snd_sof_dev *sdev, { const struct sof_ipc_window *w = container_of(ext_hdr, struct sof_ipc_window, ext_hdr); - size_t w_size = struct_size(w, window, w->num_windows); - - if (sdev->info_window) { - if (memcmp(sdev->info_window, w, w_size)) { - dev_err(sdev->dev, "error: mistmatch between window descriptor from extended manifest and mailbox"); - return -EINVAL; - } - return 0; - } if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) return -EINVAL; /* keep a local copy of the data */ - sdev->info_window = kmemdup(w, w_size, GFP_KERNEL); + sdev->info_window = kmemdup(w, struct_size(w, window, w->num_windows), + GFP_KERNEL); if (!sdev->info_window) return -ENOMEM; @@ -49,14 +40,6 @@ static int get_cc_info(struct snd_sof_dev *sdev, const struct sof_ipc_cc_version *cc = container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); - if (sdev->cc_version) { - if (memcmp(sdev->cc_version, cc, cc->ext_hdr.hdr.size)) { - dev_err(sdev->dev, "error: receive diverged cc_version descriptions"); - return -EINVAL; - } - return 0; - } - dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", cc->name, cc->major, cc->minor, cc->micro, cc->desc, cc->optim); @@ -143,151 +126,6 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); -static int ext_man_get_fw_version(struct snd_sof_dev *sdev, - const struct sof_ext_man_elem_header *hdr) -{ - const struct sof_ext_man_fw_version *v; - - v = container_of(hdr, struct sof_ext_man_fw_version, hdr); - - memcpy(&sdev->fw_ready.version, &v->version, sizeof(v->version)); - sdev->fw_ready.flags = v->flags; - - /* log ABI versions and check FW compatibility */ - return snd_sof_ipc_valid(sdev); -} - -static int ext_man_get_windows(struct snd_sof_dev *sdev, - const struct sof_ext_man_elem_header *hdr) -{ - const struct sof_ipc_ext_data_hdr *w_ipc; - const struct sof_ext_man_window *w; - - w = container_of(hdr, struct sof_ext_man_window, hdr); - w_ipc = (const struct sof_ipc_ext_data_hdr *)&w->ipc_window; - - return get_ext_windows(sdev, w_ipc); -} - -static int ext_man_get_cc_info(struct snd_sof_dev *sdev, - const struct sof_ext_man_elem_header *hdr) -{ - const struct sof_ext_man_cc_version *cc; - const struct sof_ipc_ext_data_hdr *cc_version; - - cc = container_of(hdr, struct sof_ext_man_cc_version, hdr); - cc_version = (const struct sof_ipc_ext_data_hdr *)&cc->cc_version; - - return get_cc_info(sdev, cc_version); -} - -static ssize_t snd_sof_ext_man_size(const struct firmware *fw) -{ - const struct sof_ext_man_header *head = (void *)fw->data; - - /* - * assert fw size is big enough to contain extended manifest header, - * it prevents from reading unallocated memory from `head` in following - * step. - */ - if (fw->size < sizeof(*head)) - return -EINVAL; - - /* - * When fw points to extended manifest, - * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER. - */ - if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER) - return head->full_size; - - /* otherwise given fw don't have an extended manifest */ - return 0; -} - -/* parse extended FW manifest data structures */ -static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, - const struct firmware *fw) -{ - const struct sof_ext_man_elem_header *elem_hdr; - const struct sof_ext_man_header *head; - ssize_t ext_man_size; - ssize_t remaining; - uintptr_t iptr; - int ret = 0; - - head = (struct sof_ext_man_header *)fw->data; - remaining = head->full_size - head->header_size; - ext_man_size = snd_sof_ext_man_size(fw); - - /* Assert firmware starts with extended manifest */ - if (ext_man_size < 0) { - dev_err(sdev->dev, "error: exception while reading firmware extended manifest, code %d\n", - (int)ext_man_size); - return ext_man_size; - } else if (!ext_man_size) { - dev_err(sdev->dev, "error: can't parse extended manifest when it's not present\n"); - return -EINVAL; - } - - /* incompatible version */ - if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION, - head->header_version)) { - dev_err(sdev->dev, "error: extended manifest version 0x%X differ from used 0x%X\n", - head->header_version, SOF_EXT_MAN_VERSION); - return -EINVAL; - } - - /* get first extended manifest element header */ - iptr = (uintptr_t)fw->data + head->header_size; - - while (remaining > sizeof(*elem_hdr)) { - elem_hdr = (struct sof_ext_man_elem_header *)iptr; - - dev_dbg(sdev->dev, "found sof_ext_man header type %d size 0x%X\n", - elem_hdr->type, elem_hdr->size); - - if (elem_hdr->size < sizeof(*elem_hdr) || - elem_hdr->size > remaining) { - dev_err(sdev->dev, "error: invalid sof_ext_man header size, type %d size 0x%X\n", - elem_hdr->type, elem_hdr->size); - break; - } - - /* process structure data */ - switch (elem_hdr->type) { - case SOF_EXT_MAN_ELEM_FW_VERSION: - ret = ext_man_get_fw_version(sdev, elem_hdr); - break; - case SOF_EXT_MAN_ELEM_WINDOW: - ret = ext_man_get_windows(sdev, elem_hdr); - break; - case SOF_EXT_MAN_ELEM_CC_VERSION: - ret = ext_man_get_cc_info(sdev, elem_hdr); - break; - default: - dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", - elem_hdr->type, elem_hdr->size); - break; - } - - if (ret < 0) { - dev_err(sdev->dev, "error: failed to parse sof_ext_man header type %d size 0x%X\n", - elem_hdr->type, elem_hdr->size); - break; - } - - remaining -= elem_hdr->size; - iptr += elem_hdr->size; - } - - if (remaining) { - dev_err(sdev->dev, "error: sof_ext_man header is inconsistent\n"); - ret = -EINVAL; - } - - return ret; -} - /* * IPC Firmware ready. */ @@ -635,7 +473,6 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; const char *fw_filename; - ssize_t ext_man_size; int ret; /* Don't request firmware again if firmware is already requested */ @@ -653,33 +490,11 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", fw_filename, ret); - goto err; } else { dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename); } - /* check for extended manifest */ - ext_man_size = snd_sof_ext_man_size(plat_data->fw); - if (ext_man_size > 0) { - ret = snd_sof_fw_ext_man_parse(sdev, plat_data->fw); - - /* when no error occurred, drop extended manifest */ - if (!ret) - plat_data->fw_offset = ext_man_size; - else - dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", - fw_filename, ret); - } else if (!ext_man_size) { - /* No extended manifest, so nothing to skip during FW load */ - dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n"); - } else { - ret = ext_man_size; - dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", - fw_filename, ret); - } - -err: kfree(fw_filename); return ret; From 4aa86e05be84b0692846799fce16c233a170c559 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Wed, 22 Apr 2020 15:18:05 +0800 Subject: [PATCH 101/428] ASoC: soc-core: return true, false in snd_soc_volsw_is_stereo() Fix the following coccicheck warning: include/sound/soc.h:1271:9-10: WARNING: return of 0/1 in function 'snd_soc_volsw_is_stereo' with return type bool Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200422071805.48793-1-yanaijie@huawei.com Signed-off-by: Mark Brown --- include/sound/soc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 8f542268a889..7411546dda9f 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1270,13 +1270,13 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) { if (mc->reg == mc->rreg && mc->shift == mc->rshift) - return 0; + return false; /* * mc->reg == mc->rreg && mc->shift != mc->rshift, or * mc->reg != mc->rreg means that the control is * stereo (bits in one register or in two registers) */ - return 1; + return true; } static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, From 5d7e0b1516dfc5901d1e394f17eb55b360e7d3d3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 22 Apr 2020 09:35:50 +0100 Subject: [PATCH 102/428] ASoC: dmic: Allow GPIO operations to sleep If there is a power GPIO provided we control it from DAPM context so there is no problem with a sleeping GPIO, use the _cansleep() version of the API to allow this. Signed-off-by: Mark Brown Reviewed-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200422083550.50711-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/dmic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index f5560a49b9e5..5d079d90fd3b 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -59,14 +59,14 @@ static int dmic_aif_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: if (dmic->gpio_en) - gpiod_set_value(dmic->gpio_en, 1); + gpiod_set_value_cansleep(dmic->gpio_en, 1); if (dmic->wakeup_delay) msleep(dmic->wakeup_delay); break; case SND_SOC_DAPM_POST_PMD: if (dmic->gpio_en) - gpiod_set_value(dmic->gpio_en, 0); + gpiod_set_value_cansleep(dmic->gpio_en, 0); break; } From cade2f59e7ae3d1ccec9c1e0e971308ca6a74296 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 22 Apr 2020 16:04:43 +0300 Subject: [PATCH 103/428] ASoC: Intel: Skylake: Replace guid_copy() with import_guid() There is a specific API to treat raw data as GUID, i.e. import_guid(). Use it instead of guid_copy() with explicit casting. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200422130443.38815-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-sst-utils.c | 2 +- sound/soc/intel/skylake/skl-topology.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index d43cbf4a71ef..b233f89517c1 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -290,7 +290,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, goto free_uuid_list; } - guid_copy(&module->uuid, (guid_t *)&mod_entry->uuid); + import_guid(&module->uuid, mod_entry->uuid); module->id = (i | (index << 12)); module->is_loadable = mod_entry->type.load_type; diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 69cd7a81bf2a..43a159f23a10 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1989,7 +1989,7 @@ 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) { - guid_copy(guid, (guid_t *)&uuid_tkn->uuid); + import_guid(guid, uuid_tkn->uuid); return 0; } @@ -3376,8 +3376,8 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, dev_err(dev, "Too many UUID tokens\n"); return -EINVAL; } - guid_copy(&skl->modules[uuid_index++]->uuid, - (guid_t *)&array->uuid->uuid); + import_guid(&skl->modules[uuid_index++]->uuid, + array->uuid->uuid); tuple_size += sizeof(*array->uuid); continue; From 76ec4aea9fd8117f064caa63ee6f7fbcb70eeb2c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 23 Apr 2020 09:39:22 +0100 Subject: [PATCH 104/428] ASoC: fsl_easrc: fix spelling mistake "prefitler" -> "prefilter" There is a spelling mistake in a deb_dbg message, fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200423083922.8159-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 233f26ff885c..97658e1f4989 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1769,7 +1769,7 @@ static void fsl_easrc_dump_firmware(struct fsl_asrc *easrc) } dev_dbg(dev, "Firmware v%u dump:\n", firm->firmware_version); - dev_dbg(dev, "Num prefitler scenarios: %u\n", firm->prefil_scen); + dev_dbg(dev, "Num prefilter scenarios: %u\n", firm->prefil_scen); dev_dbg(dev, "Num interpolation scenarios: %u\n", firm->interp_scen); dev_dbg(dev, "\nInterpolation scenarios:\n"); From fe57a92c88580ae7894b9c71d2d520ba98eb1591 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Apr 2020 15:28:05 +0100 Subject: [PATCH 105/428] ASoC: SOF: Add missing dependency on IMX_SCU This broke PowerPC allyesconfig. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20200423142805.52757-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 0e7964bf4448..f76660e91382 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -21,6 +21,7 @@ config SND_SOC_SOF_IMX_OF config SND_SOC_SOF_IMX8_SUPPORT bool "SOF support for i.MX8" + depends on IMX_SCU help This adds support for Sound Open Firmware for NXP i.MX8 platforms Say Y if you have such a device. From 0d283287a42027e8a618bcdf17b79578041ebabd Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 23 Apr 2020 18:03:10 +0200 Subject: [PATCH 106/428] ALSA: hda: Refactor Intel NHLT init NHLT fetch based on _DSM prevents ACPI table override mechanism from being utilized. Make use of acpi_get_table to enable it and get rid of redundant code. In consequence, NHLT can be overridden just like any other ACPI table, e.g.: DSDT or SSDT. Change has been verified on all Intel AVS architecture platforms, RVP and production laptops both. Change possible due to addition of NHLT signature to the list of standard ACPI tables: https://patchwork.kernel.org/patch/11463235/ Override helps not only with debug purposes but also allows user for table adjustment when one found on their production hardware is invalid. Shared official NHLT spec is now available to community at: https://01.org/blogs/intel-smart-sound-technology-audio-dsp NHLT support for iASL is still ongoing subject but should be available in nearest future. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20200423160310.28019-1-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/hda/intel-nhlt.c | 49 +++++++----------------------------------- 1 file changed, 8 insertions(+), 41 deletions(-) diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c index 99a23fe7fab9..2f741d2792d8 100644 --- a/sound/hda/intel-nhlt.c +++ b/sound/hda/intel-nhlt.c @@ -4,58 +4,25 @@ #include #include -#define NHLT_ACPI_HEADER_SIG "NHLT" - -/* Unique identification for getting NHLT blobs */ -static const guid_t osc_guid = - GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, - 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); - struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) { - acpi_handle handle; - union acpi_object *obj; - struct nhlt_resource_desc *nhlt_ptr; - struct nhlt_acpi_table *nhlt_table = NULL; + struct nhlt_acpi_table *nhlt; + acpi_status status; - handle = ACPI_HANDLE(dev); - if (!handle) { - dev_err(dev, "Didn't find ACPI_HANDLE\n"); + status = acpi_get_table(ACPI_SIG_NHLT, 0, + (struct acpi_table_header **)&nhlt); + if (ACPI_FAILURE(status)) { + dev_warn(dev, "NHLT table not found\n"); return NULL; } - obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); - - if (!obj) - return NULL; - - if (obj->type != ACPI_TYPE_BUFFER) { - dev_dbg(dev, "No NHLT table found\n"); - ACPI_FREE(obj); - return NULL; - } - - nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; - if (nhlt_ptr->length) - nhlt_table = (struct nhlt_acpi_table *) - memremap(nhlt_ptr->min_addr, nhlt_ptr->length, - MEMREMAP_WB); - ACPI_FREE(obj); - if (nhlt_table && - (strncmp(nhlt_table->header.signature, - NHLT_ACPI_HEADER_SIG, - strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { - memunmap(nhlt_table); - dev_err(dev, "NHLT ACPI header signature incorrect\n"); - return NULL; - } - return nhlt_table; + return nhlt; } EXPORT_SYMBOL_GPL(intel_nhlt_init); void intel_nhlt_free(struct nhlt_acpi_table *nhlt) { - memunmap((void *)nhlt); + acpi_put_table((struct acpi_table_header *)nhlt); } EXPORT_SYMBOL_GPL(intel_nhlt_free); From f0bd62b64016508938df9babe47f65c2c727d25c Mon Sep 17 00:00:00 2001 From: Alexander Tsoy Date: Fri, 24 Apr 2020 05:24:48 +0300 Subject: [PATCH 107/428] ALSA: usb-audio: Improve frames size computation For computation of the the next frame size current value of fs/fps and accumulated fractional parts of fs/fps are used, where values are stored in Q16.16 format. This is quite natural for computing frame size for asynchronous endpoints driven by explicit feedback, since in this case fs/fps is a value provided by the feedback endpoint and it's already in the Q format. If an error is accumulated over time, the device can adjust fs/fps value to prevent buffer overruns/underruns. But for synchronous endpoints the accuracy provided by these computations is not enough. Due to accumulated error the driver periodically produces frames with incorrect size (+/- 1 audio sample). This patch fixes this issue by implementing a different algorithm for frame size computation. It is based on accumulating of the remainders from division fs/fps and it doesn't accumulate errors over time. This new method is enabled for synchronous and adaptive playback endpoints. Signed-off-by: Alexander Tsoy Link: https://lore.kernel.org/r/20200424022449.14972-1-alexander@tsoy.me Signed-off-by: Takashi Iwai --- sound/usb/card.h | 4 ++++ sound/usb/endpoint.c | 43 ++++++++++++++++++++++++++++++++++++++----- sound/usb/endpoint.h | 1 + sound/usb/pcm.c | 2 ++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 395403a2d33f..820e564656ed 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -84,6 +84,10 @@ struct snd_usb_endpoint { dma_addr_t sync_dma; /* DMA address of syncbuf */ unsigned int pipe; /* the data i/o pipe */ + unsigned int framesize[2]; /* small/large frame sizes in samples */ + unsigned int sample_rem; /* remainder from division fs/fps */ + unsigned int sample_accum; /* sample accumulator */ + unsigned int fps; /* frames per second */ unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ int freqshift; /* how much to shift the feedback value to get Q16.16 */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 4a9a2f6ef5a4..d8dc7cb56d43 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -124,12 +124,12 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep) /* * For streaming based on information derived from sync endpoints, - * prepare_outbound_urb_sizes() will call next_packet_size() to + * prepare_outbound_urb_sizes() will call slave_next_packet_size() to * determine the number of samples to be sent in the next packet. * - * For implicit feedback, next_packet_size() is unused. + * For implicit feedback, slave_next_packet_size() is unused. */ -int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep) +int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep) { unsigned long flags; int ret; @@ -146,6 +146,29 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep) return ret; } +/* + * For adaptive and synchronous endpoints, prepare_outbound_urb_sizes() + * will call next_packet_size() to determine the number of samples to be + * sent in the next packet. + */ +int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep) +{ + int ret; + + if (ep->fill_max) + return ep->maxframesize; + + ep->sample_accum += ep->sample_rem; + if (ep->sample_accum >= ep->fps) { + ep->sample_accum -= ep->fps; + ret = ep->framesize[1]; + } else { + ret = ep->framesize[0]; + } + + return ret; +} + static void retire_outbound_urb(struct snd_usb_endpoint *ep, struct snd_urb_ctx *urb_ctx) { @@ -190,6 +213,8 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, if (ctx->packet_size[i]) counts = ctx->packet_size[i]; + else if (ep->sync_master) + counts = snd_usb_endpoint_slave_next_packet_size(ep); else counts = snd_usb_endpoint_next_packet_size(ep); @@ -874,10 +899,17 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, ep->maxpacksize = fmt->maxpacksize; ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX); - if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) + if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) { ep->freqn = get_usb_full_speed_rate(rate); - else + ep->fps = 1000; + } else { ep->freqn = get_usb_high_speed_rate(rate); + ep->fps = 8000; + } + + ep->sample_rem = rate % ep->fps; + ep->framesize[0] = rate / ep->fps; + ep->framesize[1] = (rate + (ep->fps - 1)) / ep->fps; /* calculate the frequency in 16.16 format */ ep->freqm = ep->freqn; @@ -936,6 +968,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) ep->active_mask = 0; ep->unlink_mask = 0; ep->phase = 0; + ep->sample_accum = 0; snd_usb_endpoint_start_quirk(ep); diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 63a39d4fa8d8..d23fa0a8c11b 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -28,6 +28,7 @@ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep); void snd_usb_endpoint_free(struct snd_usb_endpoint *ep); int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); +int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep); int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep); void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index a4e4064f9aee..b50965ab3b3a 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1579,6 +1579,8 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, for (i = 0; i < ctx->packets; i++) { if (ctx->packet_size[i]) counts = ctx->packet_size[i]; + else if (ep->sync_master) + counts = snd_usb_endpoint_slave_next_packet_size(ep); else counts = snd_usb_endpoint_next_packet_size(ep); From 04c96460bfdb483de5aaad0f9f75b2f3eca500be Mon Sep 17 00:00:00 2001 From: Alexander Tsoy Date: Fri, 24 Apr 2020 05:24:49 +0300 Subject: [PATCH 108/428] ALSA: usb-audio: Remove async workaround for Scarlett 2nd gen Frame size computation has been fixed and the workaround is no longer needed. Signed-off-by: Alexander Tsoy Link: https://lore.kernel.org/r/20200424022449.14972-2-alexander@tsoy.me Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 351ba214a9d3..a8ece1701068 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1806,20 +1806,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, */ fp->attributes &= ~UAC_EP_CS_ATTR_FILL_MAX; break; - case USB_ID(0x1235, 0x8200): /* Focusrite Scarlett 2i4 2nd gen */ - case USB_ID(0x1235, 0x8202): /* Focusrite Scarlett 2i2 2nd gen */ - case USB_ID(0x1235, 0x8205): /* Focusrite Scarlett Solo 2nd gen */ - /* - * Reports that playback should use Synch: Synchronous - * while still providing a feedback endpoint. - * Synchronous causes snapping on some sample rates. - * Force it to use Synch: Asynchronous. - */ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE; - fp->ep_attr |= USB_ENDPOINT_SYNC_ASYNC; - } - break; } } From 5b6cc38f3f3f37109ce72b60bda215a5f6892c0b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 24 Apr 2020 09:40:16 +0200 Subject: [PATCH 109/428] ALSA: usb-audio: Fix racy list management in output queue The linked list entry from FIFO is peeked at queue_pending_output_urbs() but the actual element pop-out is performed outside the spinlock, and it's potentially racy. Do delete the link at the right place inside the spinlock. Fixes: 8fdff6a319e7 ("ALSA: snd-usb: implement new endpoint streaming model") Link: https://lore.kernel.org/r/20200424074016.14301-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index d8dc7cb56d43..50104f658ed4 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -346,17 +346,17 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) ep->next_packet_read_pos %= MAX_URBS; /* take URB out of FIFO */ - if (!list_empty(&ep->ready_playback_urbs)) + if (!list_empty(&ep->ready_playback_urbs)) { ctx = list_first_entry(&ep->ready_playback_urbs, struct snd_urb_ctx, ready_list); + list_del_init(&ctx->ready_list); + } } spin_unlock_irqrestore(&ep->lock, flags); if (ctx == NULL) return; - list_del_init(&ctx->ready_list); - /* copy over the length information */ for (i = 0; i < packet->packets; i++) ctx->packet_size[i] = packet->packet_size[i]; From c38b608504aa1ad8bfa00d85abd61cffad57f27f Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 24 Apr 2020 10:01:38 +0800 Subject: [PATCH 110/428] ASoC: wm8962: set CLOCKING2 as non-volatile register Previously CLOCKING2 is set as a volatile register, but cause issue at suspend & resume, that some bits of CLOCKING2 is not restored at resume, for example SYSCLK_SRC bits, then the output clock is wrong. The volatile property is caused by CLASSD_CLK_DIV bits, which are controlled by the chip itself. But the datasheet claims these are read only and protected by the security key, and they are not read by the driver at all. So it should be safe to change CLOCKING2 to be non-volatile. Signed-off-by: Shengjiu Wang Acked-by: Charles Keepax Link: https://lore.kernel.org/r/6d25d5b36d4b9aeb8655b5e947dad52214e34177.1587693523.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d9d59f45833f..0a2cfff44441 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -118,7 +118,7 @@ static const struct reg_default wm8962_reg[] = { { 5, 0x0018 }, /* R5 - ADC & DAC Control 1 */ { 6, 0x2008 }, /* R6 - ADC & DAC Control 2 */ { 7, 0x000A }, /* R7 - Audio Interface 0 */ - + { 8, 0x01E4 }, /* R8 - Clocking2 */ { 9, 0x0300 }, /* R9 - Audio Interface 1 */ { 10, 0x00C0 }, /* R10 - Left DAC volume */ { 11, 0x00C0 }, /* R11 - Right DAC volume */ @@ -788,7 +788,6 @@ static bool wm8962_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case WM8962_CLOCKING1: - case WM8962_CLOCKING2: case WM8962_SOFTWARE_RESET: case WM8962_THERMAL_SHUTDOWN_STATUS: case WM8962_ADDITIONAL_CONTROL_4: From 3e645a4add53eec22f3818c9da01c19191525096 Mon Sep 17 00:00:00 2001 From: Rong Chen Date: Fri, 24 Apr 2020 08:54:37 +0800 Subject: [PATCH 111/428] ASoC: soc-compress: avoid false-positive Wuninitialized warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc-6.5 and earlier show a new warning: sound/soc/soc-compress.c: In function ‘soc_compr_open’: sound/soc/soc-compress.c:75:28: warning: ‘component’ is used uninitialized in this function [-Wuninitialized] struct snd_soc_component *component, *save = NULL; ^~~~~~~~~ Simplest fix is to initialize it to avoid the warning. Reported-by: kbuild test robot Signed-off-by: Rong Chen Acked-by: Kuninori Morimoto Cc: Kuninori Morimoto Link: https://lore.kernel.org/lkml/202004201540.vYPhhYMs%25lkp@intel.com Link: https://lore.kernel.org/r/20200424005437.3941-1-rong.a.chen@intel.com Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index ceaf976db0bb..8431ff72be63 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -72,7 +72,7 @@ static int soc_compr_components_free(struct snd_compr_stream *cstream, static int soc_compr_open(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_component *component, *save = NULL; + struct snd_soc_component *component = NULL, *save = NULL; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret, i; From b8d3ad51dfec3631763cfef3d30c16f40140058b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 24 Apr 2020 11:25:20 +0200 Subject: [PATCH 112/428] ASoC: snd-sof-intel-hda-common - add hda_model parameter and pass it to HDA codec driver It may be useful to pass the specific model to the generic HDA codec routines like the legacy HDA driver (snd-hda-intel) allows. The model name "sofbus" is tricky anyway. Original proposal: https://lore.kernel.org/alsa-devel/20191203161908.7496-1-perex@perex.cz/ Signed-off-by: Jaroslav Kysela Reviewed-by: Takashi Iwai Reviewed-by: Kai Vehmanen Cc: Pierre-Louis Bossart Cc: Mark Brown Link: https://lore.kernel.org/r/20200424092520.23989-1-perex@perex.cz Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 263937357ea3..337dce3b5def 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -280,6 +280,10 @@ module_param_named(use_msi, hda_use_msi, bool, 0444); MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode"); #endif +static char *hda_model; +module_param(hda_model, charp, 0444); +MODULE_PARM_DESC(hda_model, "Use the given HDA board model."); + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) static int hda_dmic_num = -1; module_param_named(dmic_num, hda_dmic_num, int, 0444); @@ -501,7 +505,7 @@ static int hda_init(struct snd_sof_dev *sdev) mutex_init(&hbus->prepare_mutex); hbus->pci = pci; hbus->mixer_assigned = -1; - hbus->modelname = "sofbus"; + hbus->modelname = hda_model; /* initialise hdac bus */ bus->addr = pci_resource_start(pci, 0); From 1fecbb71fe0e46b886f84e3b6decca6643c3af6d Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 27 Apr 2020 14:23:21 +0800 Subject: [PATCH 113/428] ASoC: fsl_esai: Disable exception interrupt before scheduling tasklet Disable exception interrupt before scheduling tasklet, otherwise if the tasklet isn't handled immediately, there will be endless xrun interrupt. Fixes: 7ccafa2b3879 ("ASoC: fsl_esai: recover the channel swap after xrun") Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/a8f2ad955aac9e52587beedc1133b3efbe746895.1587968824.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index c7a49d03463a..84290be778f0 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -87,6 +87,10 @@ static irqreturn_t esai_isr(int irq, void *devid) if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) && esai_priv->reset_at_xrun) { dev_dbg(&pdev->dev, "reset module for xrun\n"); + regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, + ESAI_xCR_xEIE_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, + ESAI_xCR_xEIE_MASK, 0); tasklet_schedule(&esai_priv->task); } From e782ddbb0873d4d96bda890b295130696e0739fc Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Mon, 27 Apr 2020 17:11:45 +0800 Subject: [PATCH 114/428] ASoC: hisilicon: Use IS_ERR() instead of IS_ERR_OR_NULL() In the function hi6210_i2s_probe(), devm_clk_get() doesn't return NULL. Thus use IS_ERR() to validate the return value instead of IS_ERR_OR_NULL(). Signed-off-by: Zhang Shengju Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200427091145.4268-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/hisilicon/hi6210-i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index ab3b76d298b3..f14ce025327a 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c @@ -570,12 +570,12 @@ static int hi6210_i2s_probe(struct platform_device *pdev) return PTR_ERR(i2s->sysctrl); i2s->clk[CLK_DACODEC] = devm_clk_get(&pdev->dev, "dacodec"); - if (IS_ERR_OR_NULL(i2s->clk[CLK_DACODEC])) + if (IS_ERR(i2s->clk[CLK_DACODEC])) return PTR_ERR(i2s->clk[CLK_DACODEC]); i2s->clocks++; i2s->clk[CLK_I2S_BASE] = devm_clk_get(&pdev->dev, "i2s-base"); - if (IS_ERR_OR_NULL(i2s->clk[CLK_I2S_BASE])) + if (IS_ERR(i2s->clk[CLK_I2S_BASE])) return PTR_ERR(i2s->clk[CLK_I2S_BASE]); i2s->clocks++; From b1ca2f63e20b471e8f86e35b4b5f9407f8cb3021 Mon Sep 17 00:00:00 2001 From: randerwang Date: Mon, 20 Apr 2020 02:35:09 +0800 Subject: [PATCH 115/428] ASoC: Intel: sof_sdw: add amp number in components string for ucm The number of speaker amplifiers may vary between platforms. UCM needs to check amp number to include different configuration files. This patch keeps track of the number of speaker amplifiers and stores it in components string of the card. Tested on Comet Lake platforms. Signed-off-by: randerwang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200419183509.4134-1-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6a1b51c0546b..cffc790fc2ea 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -909,6 +909,7 @@ static int mc_probe(struct platform_device *pdev) struct snd_soc_card *card = &card_sof_sdw; struct snd_soc_acpi_mach *mach; struct mc_private *ctx; + int amp_num = 0, i; int ret; dev_dbg(&pdev->dev, "Entry %s\n", __func__); @@ -935,9 +936,18 @@ static int mc_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, ctx); + /* + * the default amp_num is zero for each codec and + * amp_num will only be increased for active amp + * codecs on used platform + */ + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) + amp_num += codec_info_list[i].amp_num; + card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "cfg-spk:%d", - (sof_sdw_quirk & SOF_SDW_FOUR_SPK) ? 4 : 2); + "cfg-spk:%d, cfg-amp:%d", + (sof_sdw_quirk & SOF_SDW_FOUR_SPK) + ? 4 : 2, amp_num); if (!card->components) return -ENOMEM; From e66f385354b3bd29b713d8ab8556aa889723928f Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Mon, 20 Apr 2020 22:25:09 +0800 Subject: [PATCH 116/428] ASoC: mxs-saif: Avoid unnecessary check The function mxs_saif_probe() is only called with an openfirmware platform device. Therefore there is no need to check that it has an openfirmware node. Signed-off-by: Shengju Zhang Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200420142509.9728-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 1e38ce858326..64c095b91d35 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -736,9 +736,6 @@ static int mxs_saif_probe(struct platform_device *pdev) int irq, ret = 0; struct device_node *master; - if (!np) - return -EINVAL; - saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL); if (!saif) return -ENOMEM; From 1597bfbfdb3c6e97ad0f63abedc2a26d6c1850c7 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Sun, 26 Apr 2020 17:42:38 +0800 Subject: [PATCH 117/428] ASoC: ti: remove comparison to bool in omap_mcbsp_dai_set_dai_fmt() Fix the following coccicheck warning: sound/soc/ti/omap-mcbsp.c:1188:5-11: WARNING: Comparison to bool Signed-off-by: Jason Yan Acked-by: Jarkko Nikula Link: https://lore.kernel.org/r/20200426094238.23914-1-yanaijie@huawei.com Signed-off-by: Mark Brown --- sound/soc/ti/omap-mcbsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 3d41ca2238d4..0348963f4df7 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -1185,7 +1185,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, default: return -EINVAL; } - if (inv_fs == true) + if (inv_fs) regs->pcr0 ^= FSXP | FSRP; return 0; From f3fc1ea011f09156886e8f4beb240ea814f2197a Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Sat, 25 Apr 2020 15:19:29 +0800 Subject: [PATCH 118/428] ASoC: fsl_easrc: Check for null pointer before dereferencing "ctx" in fsl_easrc_hw_free() The patch 955ac624058f: "ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers" from Apr 16, 2020, leads to the following Smatch complaint: sound/soc/fsl/fsl_easrc.c:1529 fsl_easrc_hw_free() warn: variable dereferenced before check 'ctx' (see line 1527) sound/soc/fsl/fsl_easrc.c 1526 struct fsl_asrc_pair *ctx = runtime->private_data; 1527 struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; ^^^^^ Dereference 1528 1529 if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) { ^^^ This check is too late, to prevent a NULL dereference. 1530 ctx_priv->ctx_streams &= ~BIT(substream->stream); 1531 fsl_easrc_release_context(ctx); Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers") Reported-by: Dan Carpenter Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/d23c939f1c9eeb3fce34b6c34d44e2d6156f663a.1587799355.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 97658e1f4989..20326bffab64 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1524,9 +1524,14 @@ static int fsl_easrc_hw_free(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *ctx = runtime->private_data; - struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; + struct fsl_easrc_ctx_priv *ctx_priv; - if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) { + if (!ctx) + return -EINVAL; + + ctx_priv = ctx->private; + + if (ctx_priv->ctx_streams & BIT(substream->stream)) { ctx_priv->ctx_streams &= ~BIT(substream->stream); fsl_easrc_release_context(ctx); } From 77060f4f71dfb08309f461766d2e7453ce68aa76 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Mon, 27 Apr 2020 17:15:20 +0800 Subject: [PATCH 119/428] ASoC: hisilicon: Use the defined variable to clean code Use the defined variable "dev" to make the code cleaner. Signed-off-by: Zhang Shengju Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200427091520.12412-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/hisilicon/hi6210-i2s.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index f14ce025327a..fd5dcd6b9f85 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c @@ -547,7 +547,7 @@ static int hi6210_i2s_probe(struct platform_device *pdev) struct resource *res; int ret; - i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); + i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); if (!i2s) return -ENOMEM; @@ -562,28 +562,28 @@ static int hi6210_i2s_probe(struct platform_device *pdev) i2s->base_phys = (phys_addr_t)res->start; i2s->dai = hi6210_i2s_dai_init; - dev_set_drvdata(&pdev->dev, i2s); + dev_set_drvdata(dev, i2s); i2s->sysctrl = syscon_regmap_lookup_by_phandle(node, "hisilicon,sysctrl-syscon"); if (IS_ERR(i2s->sysctrl)) return PTR_ERR(i2s->sysctrl); - i2s->clk[CLK_DACODEC] = devm_clk_get(&pdev->dev, "dacodec"); + i2s->clk[CLK_DACODEC] = devm_clk_get(dev, "dacodec"); if (IS_ERR(i2s->clk[CLK_DACODEC])) return PTR_ERR(i2s->clk[CLK_DACODEC]); i2s->clocks++; - i2s->clk[CLK_I2S_BASE] = devm_clk_get(&pdev->dev, "i2s-base"); + i2s->clk[CLK_I2S_BASE] = devm_clk_get(dev, "i2s-base"); if (IS_ERR(i2s->clk[CLK_I2S_BASE])) return PTR_ERR(i2s->clk[CLK_I2S_BASE]); i2s->clocks++; - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); + ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0); if (ret) return ret; - ret = devm_snd_soc_register_component(&pdev->dev, &hi6210_i2s_i2s_comp, + ret = devm_snd_soc_register_component(dev, &hi6210_i2s_i2s_comp, &i2s->dai, 1); return ret; } From 1b290ef023b3eeb4f4688b582fecb773915ef937 Mon Sep 17 00:00:00 2001 From: Mateusz Gorski Date: Mon, 27 Apr 2020 15:27:25 +0200 Subject: [PATCH 120/428] ASoC: Intel: Skylake: Add alternative topology binary name Add alternative topology binary file name based on used machine driver and fallback to use this name after failed attempt to load topology file with name based on NHLT. This change addresses multiple issues with current mechanism, for example - there are devices without NHLT table, and that currently results in tplg_name being empty. Signed-off-by: Mateusz Gorski Reviewed-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200427132727.24942-2-mateusz.gorski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 43a159f23a10..8198d5c5a590 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -3565,8 +3566,20 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) ret = request_firmware(&fw, skl->tplg_name, bus->dev); if (ret < 0) { - dev_info(bus->dev, "tplg fw %s load failed with %d, falling back to dfw_sst.bin", - skl->tplg_name, ret); + char alt_tplg_name[64]; + + snprintf(alt_tplg_name, sizeof(alt_tplg_name), "%s-tplg.bin", + skl->mach->drv_name); + dev_info(bus->dev, "tplg fw %s load failed with %d, trying alternative tplg name %s", + skl->tplg_name, ret, alt_tplg_name); + + ret = request_firmware(&fw, alt_tplg_name, bus->dev); + if (!ret) + goto component_load; + + dev_info(bus->dev, "tplg %s failed with %d, falling back to dfw_sst.bin", + alt_tplg_name, ret); + ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); if (ret < 0) { dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n", @@ -3575,6 +3588,8 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) } } +component_load: + /* * The complete tplg for SKL is loaded as index 0, we don't use * any other index From 1b450791d517d4d6666ab9ab6d9a20c8819e3572 Mon Sep 17 00:00:00 2001 From: Mateusz Gorski Date: Mon, 27 Apr 2020 15:27:26 +0200 Subject: [PATCH 121/428] ASoC: Intel: Multiple I/O PCM format support for pipe For pipes supporting multiple input/output formats, kcontrol is created and selection of pipe input and output configuration is done based on control set. If more than one configuration is supported, then this patch allows user to select configuration of choice using amixer settings. Signed-off-by: Mateusz Gorski Signed-off-by: Pavan K S Reviewed-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200427132727.24942-3-mateusz.gorski@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/skl-tplg-interface.h | 1 + sound/soc/intel/skylake/skl-topology.c | 95 +++++++++++++++++++++++++ sound/soc/intel/skylake/skl-topology.h | 1 + 3 files changed, 97 insertions(+) diff --git a/include/uapi/sound/skl-tplg-interface.h b/include/uapi/sound/skl-tplg-interface.h index 9eee32f5e407..f2711186c81f 100644 --- a/include/uapi/sound/skl-tplg-interface.h +++ b/include/uapi/sound/skl-tplg-interface.h @@ -18,6 +18,7 @@ */ #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 #define SKL_CONTROL_TYPE_MIC_SELECT 0x102 +#define SKL_CONTROL_TYPE_MULTI_IO_SELECT 0x103 #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ #define MAX_IN_QUEUE 8 diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 8198d5c5a590..f30c531d21bc 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -579,6 +579,38 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, return ret; } +static bool skl_tplg_is_multi_fmt(struct skl_dev *skl, struct skl_pipe *pipe) +{ + struct skl_pipe_fmt *cur_fmt; + struct skl_pipe_fmt *next_fmt; + int i; + + if (pipe->nr_cfgs <= 1) + return false; + + if (pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) + return true; + + for (i = 0; i < pipe->nr_cfgs - 1; i++) { + if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) { + cur_fmt = &pipe->configs[i].out_fmt; + next_fmt = &pipe->configs[i + 1].out_fmt; + } else { + cur_fmt = &pipe->configs[i].in_fmt; + next_fmt = &pipe->configs[i + 1].in_fmt; + } + + if (!CHECK_HW_PARAMS(cur_fmt->channels, cur_fmt->freq, + cur_fmt->bps, + next_fmt->channels, + next_fmt->freq, + next_fmt->bps)) + return true; + } + + return false; +} + /* * Here, we select pipe format based on the pipe type and pipe * direction to determine the current config index for the pipeline. @@ -601,6 +633,14 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) return 0; } + if (skl_tplg_is_multi_fmt(skl, pipe)) { + pipe->cur_config_idx = pipe->pipe_config_idx; + pipe->memory_pages = pconfig->mem_pages; + dev_dbg(skl->dev, "found pipe config idx:%d\n", + pipe->cur_config_idx); + return 0; + } + if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { dev_dbg(skl->dev, "No conn_type detected, take 0th config\n"); pipe->cur_config_idx = 0; @@ -1315,6 +1355,56 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, return 0; } +static int skl_tplg_multi_config_set_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + bool is_set) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct hdac_bus *bus = snd_soc_component_get_drvdata(component); + struct skl_dev *skl = bus_to_skl(bus); + struct skl_pipeline *ppl; + struct skl_pipe *pipe = NULL; + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + u32 *pipe_id; + + if (!ec) + return -EINVAL; + + if (is_set && ucontrol->value.enumerated.item[0] > ec->items) + return -EINVAL; + + pipe_id = ec->dobj.private; + + list_for_each_entry(ppl, &skl->ppl_list, node) { + if (ppl->pipe->ppl_id == *pipe_id) { + pipe = ppl->pipe; + break; + } + } + if (!pipe) + return -EIO; + + if (is_set) + pipe->pipe_config_idx = ucontrol->value.enumerated.item[0]; + else + ucontrol->value.enumerated.item[0] = pipe->pipe_config_idx; + + return 0; +} + +static int skl_tplg_multi_config_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false); +} + +static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); +} + static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, unsigned int __user *data, unsigned int size) { @@ -1854,6 +1944,11 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { .get = skl_tplg_mic_control_get, .put = skl_tplg_mic_control_set, }, + { + .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT, + .get = skl_tplg_multi_config_get, + .put = skl_tplg_multi_config_set, + }, }; static int skl_tplg_fill_pipe_cfg(struct device *dev, diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index e967800dbb62..06576147cc29 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -306,6 +306,7 @@ struct skl_pipe { struct skl_path_config configs[SKL_MAX_PATH_CONFIGS]; struct list_head w_list; bool passthru; + u32 pipe_config_idx; }; enum skl_module_state { From 2d744ecf2b98405723a2138a547e5c75009bc4e5 Mon Sep 17 00:00:00 2001 From: Mateusz Gorski Date: Mon, 27 Apr 2020 15:27:27 +0200 Subject: [PATCH 122/428] ASoC: Intel: Skylake: Automatic DMIC format configuration according to information from NHLT Automatically choose DMIC pipeline format configuration depending on information included in NHLT. Change the access rights of appropriate kcontrols to read-only in order to prevent user interference. Signed-off-by: Mateusz Gorski Reviewed-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200427132727.24942-4-mateusz.gorski@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/skl-tplg-interface.h | 1 + sound/soc/intel/skylake/skl-topology.c | 64 +++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/include/uapi/sound/skl-tplg-interface.h b/include/uapi/sound/skl-tplg-interface.h index f2711186c81f..a93c0decfdd5 100644 --- a/include/uapi/sound/skl-tplg-interface.h +++ b/include/uapi/sound/skl-tplg-interface.h @@ -19,6 +19,7 @@ #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 #define SKL_CONTROL_TYPE_MIC_SELECT 0x102 #define SKL_CONTROL_TYPE_MULTI_IO_SELECT 0x103 +#define SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC 0x104 #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ #define MAX_IN_QUEUE 8 diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index f30c531d21bc..b9aab47d1202 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1405,6 +1405,18 @@ static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol, return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); } +static int skl_tplg_multi_config_get_dmic(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false); +} + +static int skl_tplg_multi_config_set_dmic(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); +} + static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, unsigned int __user *data, unsigned int size) { @@ -1949,6 +1961,11 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { .get = skl_tplg_multi_config_get, .put = skl_tplg_multi_config_set, }, + { + .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC, + .get = skl_tplg_multi_config_get_dmic, + .put = skl_tplg_multi_config_set_dmic, + } }; static int skl_tplg_fill_pipe_cfg(struct device *dev, @@ -3109,12 +3126,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, case SND_SOC_TPLG_CTL_ENUM: tplg_ec = container_of(hdr, struct snd_soc_tplg_enum_control, hdr); - if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { + if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) { se = (struct soc_enum *)kctl->private_value; if (tplg_ec->priv.size) - return skl_init_enum_data(bus->dev, se, - tplg_ec); + skl_init_enum_data(bus->dev, se, tplg_ec); } + + /* + * now that the control initializations are done, remove + * write permission for the DMIC configuration enums to + * avoid conflicts between NHLT settings and user interaction + */ + + if (hdr->ops.get == SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC) + kctl->access = SNDRV_CTL_ELEM_ACCESS_READ; + break; default: @@ -3584,6 +3610,37 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, return 0; } +static void skl_tplg_complete(struct snd_soc_component *component) +{ + struct snd_soc_dobj *dobj; + struct snd_soc_acpi_mach *mach = + dev_get_platdata(component->card->dev); + int i; + + list_for_each_entry(dobj, &component->dobj_list, list) { + struct snd_kcontrol *kcontrol = dobj->control.kcontrol; + struct soc_enum *se = + (struct soc_enum *)kcontrol->private_value; + char **texts = dobj->control.dtexts; + char chan_text[4]; + + if (dobj->type != SND_SOC_DOBJ_ENUM || + dobj->control.kcontrol->put != + skl_tplg_multi_config_set_dmic) + continue; + sprintf(chan_text, "c%d", mach->mach_params.dmic_num); + + for (i = 0; i < se->items; i++) { + struct snd_ctl_elem_value val; + + if (strstr(texts[i], chan_text)) { + val.value.enumerated.item[0] = i; + kcontrol->put(kcontrol, &val); + } + } + } +} + static struct snd_soc_tplg_ops skl_tplg_ops = { .widget_load = skl_tplg_widget_load, .control_load = skl_tplg_control_load, @@ -3593,6 +3650,7 @@ static struct snd_soc_tplg_ops skl_tplg_ops = { .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), .manifest = skl_manifest_load, .dai_load = skl_dai_load, + .complete = skl_tplg_complete, }; /* From a697ae6ea56e23397341b027098c1b11d9ab13da Mon Sep 17 00:00:00 2001 From: Xiyu Yang Date: Sat, 25 Apr 2020 20:48:35 +0800 Subject: [PATCH 123/428] ASoC: davinci-mcasp: Fix dma_chan refcnt leak when getting dma type davinci_mcasp_get_dma_type() invokes dma_request_chan(), which returns a reference of the specified dma_chan object to "chan" with increased refcnt. When davinci_mcasp_get_dma_type() returns, local variable "chan" becomes invalid, so the refcount should be decreased to keep refcount balanced. The reference counting issue happens in one exception handling path of davinci_mcasp_get_dma_type(). When chan device is NULL, the function forgets to decrease the refcnt increased by dma_request_chan(), causing a refcnt leak. Fix this issue by calling dma_release_channel() when chan device is NULL. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/1587818916-38730-1-git-send-email-xiyuyang19@fudan.edu.cn Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 734ffe925c4d..7a7db743dc5b 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -1896,8 +1896,10 @@ static int davinci_mcasp_get_dma_type(struct davinci_mcasp *mcasp) PTR_ERR(chan)); return PTR_ERR(chan); } - if (WARN_ON(!chan->device || !chan->device->dev)) + if (WARN_ON(!chan->device || !chan->device->dev)) { + dma_release_channel(chan); return -EINVAL; + } if (chan->device->dev->of_node) ret = of_property_read_string(chan->device->dev->of_node, From be8499c48f115b912f5747c420f66a5e2c31defe Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 27 Apr 2020 15:36:08 -0500 Subject: [PATCH 124/428] ASoC: tlv320adcx140: Fix mic gain registers Fix the mic gain registers for channels 2-4. The incorret register was being set as it was touching the CH1 config registers. Fixes: 37bde5acf040 ("ASoC: tlv320adcx140: Add the tlv320adcx140 codec driver family") Signed-off-by: Dan Murphy Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200427203608.7031-1-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 38897568ee96..0f713efde046 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -511,11 +511,11 @@ static const struct snd_soc_dapm_route adcx140_audio_map[] = { static const struct snd_kcontrol_new adcx140_snd_controls[] = { SOC_SINGLE_TLV("Analog CH1 Mic Gain Volume", ADCX140_CH1_CFG1, 2, 42, 0, adc_tlv), - SOC_SINGLE_TLV("Analog CH2 Mic Gain Volume", ADCX140_CH1_CFG2, 2, 42, 0, + SOC_SINGLE_TLV("Analog CH2 Mic Gain Volume", ADCX140_CH2_CFG1, 2, 42, 0, adc_tlv), - SOC_SINGLE_TLV("Analog CH3 Mic Gain Volume", ADCX140_CH1_CFG3, 2, 42, 0, + SOC_SINGLE_TLV("Analog CH3 Mic Gain Volume", ADCX140_CH3_CFG1, 2, 42, 0, adc_tlv), - SOC_SINGLE_TLV("Analog CH4 Mic Gain Volume", ADCX140_CH1_CFG4, 2, 42, 0, + SOC_SINGLE_TLV("Analog CH4 Mic Gain Volume", ADCX140_CH4_CFG1, 2, 42, 0, adc_tlv), SOC_SINGLE_TLV("DRE Threshold", ADCX140_DRE_CFG0, 4, 9, 0, From 4262ddc2ad631ef92058df23b1de1457543514df Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 27 Apr 2020 09:52:08 -0700 Subject: [PATCH 125/428] ASoC: Intel: boards: add explicit dependency on GPIOLIB when DMIC is used SND_SOC_DMIC depends on GPIOLIB, so let's add the dependency before selecting SND_SOC_DMIC. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200427165211.23463-2-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index c57bc6d0f145..3ee7c006a860 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -243,7 +243,7 @@ if SND_SOC_INTEL_SKL config SND_SOC_INTEL_SKL_RT286_MACH tristate "SKL with RT286 I2S mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_RT286 select SND_SOC_DMIC @@ -256,7 +256,7 @@ config SND_SOC_INTEL_SKL_RT286_MACH config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH tristate "SKL with NAU88L25 and SSM4567 in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_NAU8825 select SND_SOC_SSM4567 @@ -270,7 +270,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH tristate "SKL with NAU88L25 and MAX98357A in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_NAU8825 select SND_SOC_MAX98357A @@ -299,7 +299,7 @@ if SND_SOC_INTEL_APL config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH tristate "Broxton with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON @@ -311,7 +311,7 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH config SND_SOC_INTEL_BXT_RT298_MACH tristate "Broxton with RT298 I2S mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_RT298 select SND_SOC_DMIC @@ -328,7 +328,7 @@ if SND_SOC_INTEL_KBL config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH tristate "KBL with RT5663 and MAX98927 in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_RT5663 select SND_SOC_MAX98927 @@ -370,7 +370,7 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH tristate "KBL with DA7219 and MAX98927 in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_DA7219 select SND_SOC_MAX98927 @@ -400,7 +400,7 @@ if SND_SOC_SOF_GEMINILAKE && SND_SOC_SOF_HDA_LINK config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH tristate "GLK with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON @@ -412,7 +412,7 @@ config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH tristate "GLK with RT5682 and MAX98357A in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_RT5682 @@ -432,6 +432,7 @@ if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH tristate "SKL/KBL/BXT/APL with HDA Codecs" depends on SND_HDA_CODEC_HDMI + depends on GPIOLIB select SND_SOC_HDAC_HDMI select SND_SOC_DMIC # SND_SOC_HDAC_HDA is already selected @@ -446,7 +447,7 @@ endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC if SND_SOC_SOF_HDA_LINK || 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 I2C && ACPI && GPIOLIB depends on (SND_SOC_SOF_HDA_LINK && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) depends on SND_HDA_CODEC_HDMI @@ -480,7 +481,7 @@ if (SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK) config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH tristate "CML_LP with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON help @@ -491,7 +492,7 @@ config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH tristate "CML with RT1011 and RT5682 in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_RT1011 @@ -510,7 +511,7 @@ if SND_SOC_SOF_JASPERLAKE config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH tristate "SOF with DA7219 and MAX98373/MAX98360A in I2S Mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_DA7219 @@ -528,7 +529,7 @@ if SND_SOC_SOF_ELKHARTLAKE config SND_SOC_INTEL_EHL_RT5660_MACH tristate "EHL with RT5660 in I2S mode" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_RT5660 @@ -543,7 +544,7 @@ if SND_SOC_SOF_INTEL_SOUNDWIRE config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH tristate "SoundWire generic machine driver" - depends on I2C && ACPI + depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE From e241f8e77958de2b7708e72d7159952d2bd1f0fe Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Tue, 28 Apr 2020 01:13:32 +0800 Subject: [PATCH 126/428] ASoC: bdw-rt5677: add channel constraint BDW boards using this machine driver supports only stereo capture and playback. Implement a constraint to enforce it. Signed-off-by: Brent Lu Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/1588007614-25061-2-git-send-email-brent.lu@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bdw-rt5677.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index cc41a348295e..5f96d7ac0a22 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -222,6 +222,31 @@ static int bdw_rt5677_rtd_init(struct snd_soc_pcm_runtime *rtd) } #endif +static const unsigned int channels[] = { + 2, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static int bdw_rt5677_fe_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + /* Board supports stereo configuration only */ + runtime->hw.channels_max = 2; + return snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); +} + +static const struct snd_soc_ops bdw_rt5677_fe_ops = { + .startup = bdw_rt5677_fe_startup, +}; + static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) { struct bdw_rt5677_priv *bdw_rt5677 = @@ -321,6 +346,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { }, .dpcm_capture = 1, .dpcm_playback = 1, + .ops = &bdw_rt5677_fe_ops, SND_SOC_DAILINK_REG(fe, dummy, platform), }, From 08d6713a4056cab5b29eb135eecb2e97492fc8d8 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Tue, 28 Apr 2020 01:13:33 +0800 Subject: [PATCH 127/428] ASoC: bdw-rt5650: add channel constraint BDW boards using this machine driver supports only 2 or 4-channel capture. Implement a constraint to enforce it. Signed-off-by: Brent Lu Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/1588007614-25061-3-git-send-email-brent.lu@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bdw-rt5650.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index af2f50293208..a97e912adf4b 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -162,6 +162,34 @@ static int bdw_rt5650_rtd_init(struct snd_soc_pcm_runtime *rtd) } #endif +static const unsigned int channels[] = { + 2, 4, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static int bdw_rt5650_fe_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + /* Board supports stereo and quad configurations for capture */ + if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) + return 0; + + runtime->hw.channels_max = 4; + return snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); +} + +static const struct snd_soc_ops bdw_rt5650_fe_ops = { + .startup = bdw_rt5650_fe_startup, +}; + static int bdw_rt5650_init(struct snd_soc_pcm_runtime *rtd) { struct bdw_rt5650_priv *bdw_rt5650 = @@ -234,6 +262,7 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { .name = "System PCM", .stream_name = "System Playback", .dynamic = 1, + .ops = &bdw_rt5650_fe_ops, #if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) .init = bdw_rt5650_rtd_init, #endif From ad18763f46835b768714ac6de6dcf42384a261ca Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Tue, 28 Apr 2020 01:13:34 +0800 Subject: [PATCH 128/428] ASoC: broadwell: add channel constraint BDW boards using this machine driver supports only stereo capture and playback. Implement a constraint to enforce it. Signed-off-by: Brent Lu Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/1588007614-25061-4-git-send-email-brent.lu@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/broadwell.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index f9a8336a0541..07b2cfdadaeb 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -143,6 +143,31 @@ static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) } #endif +static const unsigned int channels[] = { + 2, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static int broadwell_fe_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + /* Board supports stereo configuration only */ + runtime->hw.channels_max = 2; + return snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); +} + +static const struct snd_soc_ops broadwell_fe_ops = { + .startup = broadwell_fe_startup, +}; + SND_SOC_DAILINK_DEF(system, DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); @@ -180,6 +205,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { .init = broadwell_rtd_init, #endif .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &broadwell_fe_ops, .dpcm_playback = 1, .dpcm_capture = 1, SND_SOC_DAILINK_REG(system, dummy, platform), From ac3367442d9e5971e32014c6fea41ca1662c0e2d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 28 Apr 2020 11:07:42 +0000 Subject: [PATCH 129/428] ASoC: tegra: tegra_wm8903: Use devm_snd_soc_register_card() Using devm_snd_soc_register_card() can make the code shorter and cleaner. Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20200428110742.110335-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 7bf159965c4d..d3ead0213cef 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -351,9 +351,9 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev) if (ret) return ret; - ret = snd_soc_register_card(card); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + dev_err(&pdev->dev, "devm_snd_soc_register_card failed (%d)\n", ret); return ret; } @@ -361,15 +361,6 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev) return 0; } -static int tegra_wm8903_driver_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - static const struct of_device_id tegra_wm8903_of_match[] = { { .compatible = "nvidia,tegra-audio-wm8903", }, {}, @@ -382,7 +373,6 @@ static struct platform_driver tegra_wm8903_driver = { .of_match_table = tegra_wm8903_of_match, }, .probe = tegra_wm8903_driver_probe, - .remove = tegra_wm8903_driver_remove, }; module_platform_driver(tegra_wm8903_driver); From aa7b8230d4c3d0e691604dc908887904f52f2ab8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:14:38 +0900 Subject: [PATCH 130/428] ASoC: soc-dai: add soc_dai_err() At soc-dai.c, it is good idea to indicate error function and its component name if there was error. This patch adds soc_dai_err() for it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/871rodu74x.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dai.c | 159 +++++++++++++++++++++++++++----------------- 1 file changed, 98 insertions(+), 61 deletions(-) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 31c41559034b..d591b3bd8b99 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -9,6 +9,24 @@ #include #include +#define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret) +static inline int _soc_dai_ret(struct snd_soc_dai *dai, + const char *func, int ret) +{ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + case 0: + break; + default: + dev_err(dai->dev, + "ASoC: error at %s on %s: %d\n", + func, dai->name, ret); + } + + return ret; +} + /** * snd_soc_dai_set_sysclk - configure DAI system or master clock. * @dai: DAI @@ -21,11 +39,15 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { - if (dai->driver->ops->set_sysclk) - return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); + int ret; - return snd_soc_component_set_sysclk(dai->component, clk_id, 0, - freq, dir); + if (dai->driver->ops->set_sysclk) + ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); + else + ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0, + freq, dir); + + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); @@ -42,10 +64,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) { + int ret = -EINVAL; + if (dai->driver->ops->set_clkdiv) - return dai->driver->ops->set_clkdiv(dai, div_id, div); - else - return -EINVAL; + ret = dai->driver->ops->set_clkdiv(dai, div_id, div); + + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); @@ -62,12 +86,16 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { - if (dai->driver->ops->set_pll) - return dai->driver->ops->set_pll(dai, pll_id, source, - freq_in, freq_out); + int ret; - return snd_soc_component_set_pll(dai->component, pll_id, source, - freq_in, freq_out); + if (dai->driver->ops->set_pll) + ret = dai->driver->ops->set_pll(dai, pll_id, source, + freq_in, freq_out); + else + ret = snd_soc_component_set_pll(dai->component, pll_id, source, + freq_in, freq_out); + + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); @@ -80,10 +108,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); */ int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) { + int ret = -EINVAL; + if (dai->driver->ops->set_bclk_ratio) - return dai->driver->ops->set_bclk_ratio(dai, ratio); - else - return -EINVAL; + ret = dai->driver->ops->set_bclk_ratio(dai, ratio); + + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); @@ -96,9 +126,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); */ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - if (dai->driver->ops->set_fmt == NULL) - return -ENOTSUPP; - return dai->driver->ops->set_fmt(dai, fmt); + int ret = -ENOTSUPP; + + if (dai->driver->ops->set_fmt) + ret = dai->driver->ops->set_fmt(dai, fmt); + + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); @@ -153,6 +186,8 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { + int ret = -ENOTSUPP; + if (dai->driver->ops->xlate_tdm_slot_mask) dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); @@ -163,10 +198,9 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, dai->rx_mask = rx_mask; if (dai->driver->ops->set_tdm_slot) - return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, + ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); - else - return -ENOTSUPP; + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); @@ -186,11 +220,12 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num, unsigned int *tx_slot, unsigned int rx_num, unsigned int *rx_slot) { + int ret = -ENOTSUPP; + if (dai->driver->ops->set_channel_map) - return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, - rx_num, rx_slot); - else - return -ENOTSUPP; + ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, + rx_num, rx_slot); + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); @@ -208,11 +243,12 @@ int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, unsigned int *tx_num, unsigned int *tx_slot, unsigned int *rx_num, unsigned int *rx_slot) { + int ret = -ENOTSUPP; + if (dai->driver->ops->get_channel_map) - return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, - rx_num, rx_slot); - else - return -ENOTSUPP; + ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, + rx_num, rx_slot); + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); @@ -225,10 +261,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); */ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) { + int ret = -EINVAL; + if (dai->driver->ops->set_tristate) - return dai->driver->ops->set_tristate(dai, tristate); - else - return -EINVAL; + ret = dai->driver->ops->set_tristate(dai, tristate); + + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); @@ -243,13 +281,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, int direction) { + int ret = -ENOTSUPP; + if (dai->driver->ops->mute_stream) - return dai->driver->ops->mute_stream(dai, mute, direction); + ret = dai->driver->ops->mute_stream(dai, mute, direction); else if (direction == SNDRV_PCM_STREAM_PLAYBACK && dai->driver->ops->digital_mute) - return dai->driver->ops->digital_mute(dai, mute); - else - return -ENOTSUPP; + ret = dai->driver->ops->digital_mute(dai, mute); + + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); @@ -258,29 +298,19 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - int ret; + int ret = 0; /* perform any topology hw_params fixups before DAI */ if (rtd->dai_link->be_hw_params_fixup) { ret = rtd->dai_link->be_hw_params_fixup(rtd, params); - if (ret < 0) { - dev_err(rtd->dev, - "ASoC: hw_params topology fixup failed %d\n", - ret); - return ret; - } + if (ret < 0) + goto end; } - if (dai->driver->ops->hw_params) { + if (dai->driver->ops->hw_params) ret = dai->driver->ops->hw_params(substream, params, dai); - if (ret < 0) { - dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n", - dai->name, ret); - return ret; - } - } - - return 0; +end: + return soc_dai_ret(dai, ret); } void snd_soc_dai_hw_free(struct snd_soc_dai *dai, @@ -298,7 +328,7 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, if (dai->driver->ops->startup) ret = dai->driver->ops->startup(substream, dai); - return ret; + return soc_dai_ret(dai, ret); } void snd_soc_dai_shutdown(struct snd_soc_dai *dai, @@ -316,7 +346,7 @@ int snd_soc_dai_prepare(struct snd_soc_dai *dai, if (dai->driver->ops->prepare) ret = dai->driver->ops->prepare(substream, dai); - return ret; + return soc_dai_ret(dai, ret); } int snd_soc_dai_trigger(struct snd_soc_dai *dai, @@ -340,7 +370,7 @@ int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, if (dai->driver->ops->bespoke_trigger) ret = dai->driver->ops->bespoke_trigger(substream, cmd, dai); - return ret; + return soc_dai_ret(dai, ret); } snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, @@ -356,24 +386,31 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, int snd_soc_dai_probe(struct snd_soc_dai *dai) { + int ret = 0; + if (dai->driver->probe) - return dai->driver->probe(dai); - return 0; + ret = dai->driver->probe(dai); + + return soc_dai_ret(dai, ret); } int snd_soc_dai_remove(struct snd_soc_dai *dai) { + int ret = 0; + if (dai->driver->remove) - return dai->driver->remove(dai); - return 0; + ret = dai->driver->remove(dai); + + return soc_dai_ret(dai, ret); } int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num) { + int ret = -ENOTSUPP; if (dai->driver->compress_new) - return dai->driver->compress_new(rtd, num); - return -ENOTSUPP; + ret = dai->driver->compress_new(rtd, num); + return soc_dai_ret(dai, ret); } /* From 479914ed779d408273fb3cac4c061dbe695f17cb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:14:43 +0900 Subject: [PATCH 131/428] ASoC: soc-dai: don't overwide dai->driver->ops Current ASoC overwrites null_dai_ops to dai->driver->ops if it was NULL. But, we can remove it if framework always checks dai->driver->ops when it uses DAI callbacks. This patch do it, and removes null_dai_ops. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87zhb1sskc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 5 ---- sound/soc/soc-dai.c | 58 +++++++++++++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8321e75ff244..6778eeffb48f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -742,9 +742,6 @@ static inline void soc_resume_init(struct snd_soc_card *card) } #endif -static const struct snd_soc_dai_ops null_dai_ops = { -}; - static struct device_node *soc_component_to_node(struct snd_soc_component *component) { @@ -2406,8 +2403,6 @@ struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, dai->component = component; dai->dev = dev; dai->driver = dai_drv; - if (!dai->driver->ops) - dai->driver->ops = &null_dai_ops; /* see for_each_component_dais */ list_add_tail(&dai->list, &component->dai_list); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index d591b3bd8b99..93e03c9ec164 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -41,7 +41,8 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, { int ret; - if (dai->driver->ops->set_sysclk) + if (dai->driver->ops && + dai->driver->ops->set_sysclk) ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); else ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0, @@ -66,7 +67,8 @@ int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, { int ret = -EINVAL; - if (dai->driver->ops->set_clkdiv) + if (dai->driver->ops && + dai->driver->ops->set_clkdiv) ret = dai->driver->ops->set_clkdiv(dai, div_id, div); return soc_dai_ret(dai, ret); @@ -88,7 +90,8 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, { int ret; - if (dai->driver->ops->set_pll) + if (dai->driver->ops && + dai->driver->ops->set_pll) ret = dai->driver->ops->set_pll(dai, pll_id, source, freq_in, freq_out); else @@ -110,7 +113,8 @@ int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) { int ret = -EINVAL; - if (dai->driver->ops->set_bclk_ratio) + if (dai->driver->ops && + dai->driver->ops->set_bclk_ratio) ret = dai->driver->ops->set_bclk_ratio(dai, ratio); return soc_dai_ret(dai, ret); @@ -128,7 +132,8 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { int ret = -ENOTSUPP; - if (dai->driver->ops->set_fmt) + if (dai->driver->ops && + dai->driver->ops->set_fmt) ret = dai->driver->ops->set_fmt(dai, fmt); return soc_dai_ret(dai, ret); @@ -188,7 +193,8 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, { int ret = -ENOTSUPP; - if (dai->driver->ops->xlate_tdm_slot_mask) + if (dai->driver->ops && + dai->driver->ops->xlate_tdm_slot_mask) dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); else @@ -197,7 +203,8 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, dai->tx_mask = tx_mask; dai->rx_mask = rx_mask; - if (dai->driver->ops->set_tdm_slot) + if (dai->driver->ops && + dai->driver->ops->set_tdm_slot) ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); return soc_dai_ret(dai, ret); @@ -222,7 +229,8 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, { int ret = -ENOTSUPP; - if (dai->driver->ops->set_channel_map) + if (dai->driver->ops && + dai->driver->ops->set_channel_map) ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, rx_num, rx_slot); return soc_dai_ret(dai, ret); @@ -245,7 +253,8 @@ int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, { int ret = -ENOTSUPP; - if (dai->driver->ops->get_channel_map) + if (dai->driver->ops && + dai->driver->ops->get_channel_map) ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, rx_num, rx_slot); return soc_dai_ret(dai, ret); @@ -263,7 +272,8 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) { int ret = -EINVAL; - if (dai->driver->ops->set_tristate) + if (dai->driver->ops && + dai->driver->ops->set_tristate) ret = dai->driver->ops->set_tristate(dai, tristate); return soc_dai_ret(dai, ret); @@ -283,9 +293,11 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, { int ret = -ENOTSUPP; - if (dai->driver->ops->mute_stream) + if (dai->driver->ops && + dai->driver->ops->mute_stream) ret = dai->driver->ops->mute_stream(dai, mute, direction); else if (direction == SNDRV_PCM_STREAM_PLAYBACK && + dai->driver->ops && dai->driver->ops->digital_mute) ret = dai->driver->ops->digital_mute(dai, mute); @@ -307,7 +319,8 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, goto end; } - if (dai->driver->ops->hw_params) + if (dai->driver->ops && + dai->driver->ops->hw_params) ret = dai->driver->ops->hw_params(substream, params, dai); end: return soc_dai_ret(dai, ret); @@ -316,7 +329,8 @@ end: void snd_soc_dai_hw_free(struct snd_soc_dai *dai, struct snd_pcm_substream *substream) { - if (dai->driver->ops->hw_free) + if (dai->driver->ops && + dai->driver->ops->hw_free) dai->driver->ops->hw_free(substream, dai); } @@ -325,7 +339,8 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, { int ret = 0; - if (dai->driver->ops->startup) + if (dai->driver->ops && + dai->driver->ops->startup) ret = dai->driver->ops->startup(substream, dai); return soc_dai_ret(dai, ret); @@ -334,7 +349,8 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream) { - if (dai->driver->ops->shutdown) + if (dai->driver->ops && + dai->driver->ops->shutdown) dai->driver->ops->shutdown(substream, dai); } @@ -343,7 +359,8 @@ int snd_soc_dai_prepare(struct snd_soc_dai *dai, { int ret = 0; - if (dai->driver->ops->prepare) + if (dai->driver->ops && + dai->driver->ops->prepare) ret = dai->driver->ops->prepare(substream, dai); return soc_dai_ret(dai, ret); @@ -355,7 +372,8 @@ int snd_soc_dai_trigger(struct snd_soc_dai *dai, { int ret = 0; - if (dai->driver->ops->trigger) + if (dai->driver->ops && + dai->driver->ops->trigger) ret = dai->driver->ops->trigger(substream, cmd, dai); return ret; @@ -367,7 +385,8 @@ int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, { int ret = 0; - if (dai->driver->ops->bespoke_trigger) + if (dai->driver->ops && + dai->driver->ops->bespoke_trigger) ret = dai->driver->ops->bespoke_trigger(substream, cmd, dai); return soc_dai_ret(dai, ret); @@ -378,7 +397,8 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, { int delay = 0; - if (dai->driver->ops->delay) + if (dai->driver->ops && + dai->driver->ops->delay) delay = dai->driver->ops->delay(substream, dai); return delay; From 0b73ba550cdd95b0fdca5da0040c29ae5d25ae5d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:14:48 +0900 Subject: [PATCH 132/428] ASoC: soc-dai: add snd_soc_pcm_dai_new() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update soc_dai_pcm_new() to snd_soc_pcm_dai_new(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87y2qlssk7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-core.c | 23 +---------------------- sound/soc/soc-dai.c | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index b33abe93b905..fd7e203315e6 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -170,6 +170,8 @@ int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); +int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); + struct snd_soc_dai_ops { /* * DAI clocking configuration, all optional. diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6778eeffb48f..76167fa264af 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1036,27 +1036,6 @@ _err_defer: } EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtime); -static int soc_dai_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *dai; - int i, ret = 0; - - for_each_rtd_dais(rtd, i, dai) { - struct snd_soc_dai_driver *drv = dai->driver; - - if (drv->pcm_new) - ret = drv->pcm_new(rtd, dai); - if (ret < 0) { - dev_err(dai->dev, - "ASoC: Failed to bind %s with pcm device\n", - dai->name); - return ret; - } - } - - return 0; -} - static int soc_init_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd) { @@ -1121,7 +1100,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, return ret; } - return soc_dai_pcm_new(rtd); + return snd_soc_pcm_dai_new(rtd); } static void soc_set_name_prefix(struct snd_soc_card *card, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 93e03c9ec164..1b45e6e114ad 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -445,3 +445,19 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) /* If the codec specifies any channels at all, it supports the stream */ return stream->channels_min; } + +int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *dai; + int i, ret = 0; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->pcm_new) { + ret = dai->driver->pcm_new(rtd, dai); + if (ret < 0) + return soc_dai_ret(dai, ret); + } + } + + return 0; +} From d108c7fd0b776d5b48acd15f6f52b1bb8255a69e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:14:53 +0900 Subject: [PATCH 133/428] ASoC: soc-dai: add snd_soc_pcm_dai_prepare() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update snd_soc_dai_prepare() to snd_soc_pcm_dai_prepare(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87wo65ssk2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +-- sound/soc/soc-dai.c | 30 ++++++++++++++++++------------ sound/soc/soc-pcm.c | 11 ++++------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index fd7e203315e6..1b25318b6325 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -154,8 +154,6 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); -int snd_soc_dai_prepare(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream); int snd_soc_dai_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd); int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, @@ -171,6 +169,7 @@ int snd_soc_dai_compress_new(struct snd_soc_dai *dai, bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); +int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 1b45e6e114ad..1a9cfdcfc736 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -354,18 +354,6 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, dai->driver->ops->shutdown(substream, dai); } -int snd_soc_dai_prepare(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream) -{ - int ret = 0; - - if (dai->driver->ops && - dai->driver->ops->prepare) - ret = dai->driver->ops->prepare(substream, dai); - - return soc_dai_ret(dai, ret); -} - int snd_soc_dai_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd) @@ -461,3 +449,21 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) return 0; } + +int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *dai; + int i, ret; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->ops && + dai->driver->ops->prepare) { + ret = dai->driver->ops->prepare(substream, dai); + if (ret < 0) + return soc_dai_ret(dai, ret); + } + } + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 77a680da366f..f7b3dca1d152 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -950,13 +950,10 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) } } - for_each_rtd_dais(rtd, i, dai) { - ret = snd_soc_dai_prepare(dai, substream); - if (ret < 0) { - dev_err(dai->dev, - "ASoC: DAI prepare error: %d\n", ret); - goto out; - } + ret = snd_soc_pcm_dai_prepare(substream); + if (ret < 0) { + dev_err(rtd->dev, "ASoC: DAI prepare error: %d\n", ret); + goto out; } /* cancel any delayed stream shutdown that is pending */ From 42f2472d4689c00d742b6690aa6579966f0b2f83 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:04 +0900 Subject: [PATCH 134/428] ASoC: soc-dai: add snd_soc_pcm_dai_trigger() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update snd_soc_dai_trigger() to snd_soc_pcm_dai_trigger(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87v9lpssjr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +-- sound/soc/soc-dai.c | 32 +++++++++++++++++++------------- sound/soc/soc-pcm.c | 18 ++++-------------- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1b25318b6325..3da850b4aefe 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -154,8 +154,6 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); -int snd_soc_dai_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, int cmd); int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd); snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, @@ -170,6 +168,7 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); +int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 1a9cfdcfc736..29587d7e75ca 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -354,19 +354,6 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, dai->driver->ops->shutdown(substream, dai); } -int snd_soc_dai_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, - int cmd) -{ - int ret = 0; - - if (dai->driver->ops && - dai->driver->ops->trigger) - ret = dai->driver->ops->trigger(substream, cmd, dai); - - return ret; -} - int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd) @@ -467,3 +454,22 @@ int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) return 0; } + +int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *dai; + int i, ret; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->ops && + dai->driver->ops->trigger) { + ret = dai->driver->ops->trigger(substream, cmd, dai); + if (ret < 0) + return soc_dai_ret(dai, ret); + } + } + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index f7b3dca1d152..e56500212c0c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1192,7 +1192,6 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *dai; int i, ret; ret = soc_rtd_trigger(rtd, substream, cmd); @@ -1205,27 +1204,18 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) return ret; } - for_each_rtd_dais(rtd, i, dai) { - ret = snd_soc_dai_trigger(dai, substream, cmd); - if (ret < 0) - return ret; - } - - return 0; + return snd_soc_pcm_dai_trigger(substream, cmd); } static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *dai; int i, ret; - for_each_rtd_dais(rtd, i, dai) { - ret = snd_soc_dai_trigger(dai, substream, cmd); - if (ret < 0) - return ret; - } + ret = snd_soc_pcm_dai_trigger(substream, cmd); + if (ret < 0) + return ret; for_each_rtd_components(rtd, i, component) { ret = snd_soc_component_trigger(component, substream, cmd); From 30819358ae73326269ba61597be47d5036e05b08 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:09 +0900 Subject: [PATCH 135/428] ASoC: soc-dai: add snd_soc_pcm_dai_bespoke_trigger() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update soc_pcm_bespoke_trigger() to snd_soc_pcm_dai_bespoke_trigger(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87tv19ssjm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 4 ++-- sound/soc/soc-dai.c | 33 ++++++++++++++++++++------------- sound/soc/soc-pcm.c | 21 +++------------------ 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 3da850b4aefe..a0c7ac112b86 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -154,8 +154,6 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); -int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, int cmd); snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_suspend(struct snd_soc_dai *dai); @@ -169,6 +167,8 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); +int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, + int cmd); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 29587d7e75ca..226c51b9089c 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -354,19 +354,6 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, dai->driver->ops->shutdown(substream, dai); } -int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, - int cmd) -{ - int ret = 0; - - if (dai->driver->ops && - dai->driver->ops->bespoke_trigger) - ret = dai->driver->ops->bespoke_trigger(substream, cmd, dai); - - return soc_dai_ret(dai, ret); -} - snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream) { @@ -473,3 +460,23 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, return 0; } + +int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *dai; + int i, ret; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->ops && + dai->driver->ops->bespoke_trigger) { + ret = dai->driver->ops->bespoke_trigger(substream, + cmd, dai); + if (ret < 0) + return soc_dai_ret(dai, ret); + } + } + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e56500212c0c..440c7e87829a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1252,21 +1252,6 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } -static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *dai; - int i, ret; - - for_each_rtd_dais(rtd, i, dai) { - ret = snd_soc_dai_bespoke_trigger(dai, substream, cmd); - if (ret < 0) - return ret; - } - - return 0; -} /* * soc level wrapper for pointer callback * If cpu_dai, codec_dai, component driver has the delay callback, then @@ -2470,7 +2455,7 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n", fe->dai_link->name, cmd); - ret = soc_pcm_bespoke_trigger(substream, cmd); + ret = snd_soc_pcm_dai_bespoke_trigger(substream, cmd); break; default: dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd, @@ -2615,7 +2600,7 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n", fe->dai_link->name); - err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP); + err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP); if (err < 0) dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err); } else { @@ -2693,7 +2678,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n", fe->dai_link->name); - ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START); + ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START); if (ret < 0) { dev_err(fe->dev,"ASoC: bespoke trigger FE failed %d\n", ret); goto hw_free; From 51801aeafdc9c1d55e5e71e58a1bbbd2583328fa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:15 +0900 Subject: [PATCH 136/428] ASoC: soc-dai: add snd_soc_pcm_dai_probe() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update snd_soc_dai_probe() to snd_soc_pcm_dai_probe(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87sggtssjg.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 +- sound/soc/soc-core.c | 33 +++++---------------------------- sound/soc/soc-dai.c | 32 ++++++++++++++++++++++---------- 3 files changed, 28 insertions(+), 39 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index a0c7ac112b86..bdb79df637af 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -158,12 +158,12 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); -int snd_soc_dai_probe(struct snd_soc_dai *dai); int snd_soc_dai_remove(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); +int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 76167fa264af..8cafca4e1405 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1273,26 +1273,6 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order) dai->probed = 0; } -static int soc_probe_dai(struct snd_soc_dai *dai, int order) -{ - int ret; - - if (dai->probed || - dai->driver->probe_order != order) - return 0; - - ret = snd_soc_dai_probe(dai); - if (ret < 0) { - dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n", - dai->name, ret); - return ret; - } - - dai->probed = 1; - - return 0; -} - static void soc_remove_link_dais(struct snd_soc_card *card) { int i; @@ -1311,9 +1291,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card) static int soc_probe_link_dais(struct snd_soc_card *card) { - struct snd_soc_dai *dai; struct snd_soc_pcm_runtime *rtd; - int i, order, ret; + int order, ret; for_each_comp_order(order) { for_each_card_rtds(card, rtd) { @@ -1322,12 +1301,10 @@ static int soc_probe_link_dais(struct snd_soc_card *card) "ASoC: probe %s dai link %d late %d\n", card->name, rtd->num, order); - /* probe the CPU DAI */ - for_each_rtd_dais(rtd, i, dai) { - ret = soc_probe_dai(dai, order); - if (ret) - return ret; - } + /* probe all rtd connected DAIs in good order */ + ret = snd_soc_pcm_dai_probe(rtd, order); + if (ret) + return ret; } } diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 226c51b9089c..48f5eb5ef387 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -366,16 +366,6 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, return delay; } -int snd_soc_dai_probe(struct snd_soc_dai *dai) -{ - int ret = 0; - - if (dai->driver->probe) - ret = dai->driver->probe(dai); - - return soc_dai_ret(dai, ret); -} - int snd_soc_dai_remove(struct snd_soc_dai *dai) { int ret = 0; @@ -408,6 +398,28 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) return stream->channels_min; } +int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) +{ + struct snd_soc_dai *dai; + int i; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->probe_order != order) + continue; + + if (dai->driver->probe) { + int ret = dai->driver->probe(dai); + + if (ret < 0) + return soc_dai_ret(dai, ret); + } + + dai->probed = 1; + } + + return 0; +} + int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai; From 7eaa313bdec3f2326c9cdacec88fd484a36c423b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:20 +0900 Subject: [PATCH 137/428] ASoC: soc-dai: add snd_soc_pcm_dai_remove() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update snd_soc_dai_remove() to snd_soc_pcm_dai_remove(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87r1wdssjc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 +- sound/soc/soc-core.c | 24 ++---------------------- sound/soc/soc-dai.c | 32 ++++++++++++++++++++++---------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index bdb79df637af..cf7d09f210bc 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -158,12 +158,12 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); -int snd_soc_dai_remove(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); +int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8cafca4e1405..95d8189e45ab 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1256,35 +1256,15 @@ err_probe: return ret; } -static void soc_remove_dai(struct snd_soc_dai *dai, int order) -{ - int err; - - if (!dai || !dai->probed || !dai->driver || - dai->driver->remove_order != order) - return; - - err = snd_soc_dai_remove(dai); - if (err < 0) - dev_err(dai->dev, - "ASoC: failed to remove %s: %d\n", - dai->name, err); - - dai->probed = 0; -} - static void soc_remove_link_dais(struct snd_soc_card *card) { - int i; - struct snd_soc_dai *dai; struct snd_soc_pcm_runtime *rtd; int order; for_each_comp_order(order) { for_each_card_rtds(card, rtd) { - /* remove DAIs */ - for_each_rtd_dais(rtd, i, dai) - soc_remove_dai(dai, order); + /* remove all rtd connected DAIs in good order */ + snd_soc_pcm_dai_remove(rtd, order); } } } diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 48f5eb5ef387..2bc452fe02ff 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -366,16 +366,6 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, return delay; } -int snd_soc_dai_remove(struct snd_soc_dai *dai) -{ - int ret = 0; - - if (dai->driver->remove) - ret = dai->driver->remove(dai); - - return soc_dai_ret(dai, ret); -} - int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num) { @@ -420,6 +410,28 @@ int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) return 0; } +int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order) +{ + struct snd_soc_dai *dai; + int i, r, ret = 0; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->remove_order != order) + continue; + + if (dai->probed && + dai->driver->remove) { + r = dai->driver->remove(dai); + if (r < 0) + ret = r; /* use last error */ + } + + dai->probed = 0; + } + + return ret; +} + int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai; From b5ae4ccea5ab15adcde64f4474b36e4a630434ec Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:24 +0900 Subject: [PATCH 138/428] ASoC: soc-dai: add snd_soc_dai_compr_start() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_start(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87pnbxssj7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 24 ++++++------------------ sound/soc/soc-dai.c | 13 +++++++++++++ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index cf7d09f210bc..deb99b1469b4 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -170,6 +170,9 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, int cmd); +int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream); + struct snd_soc_dai_ops { /* * DAI clocking configuration, all optional. diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 8431ff72be63..7960270f5e67 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -87,15 +87,9 @@ static int soc_compr_open(struct snd_compr_stream *cstream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) { - ret = cpu_dai->driver->cops->startup(cstream, cpu_dai); - if (ret < 0) { - dev_err(cpu_dai->dev, - "Compress ASoC: can't open interface %s: %d\n", - cpu_dai->name, ret); - goto out; - } - } + ret = snd_soc_dai_compr_startup(cpu_dai, cstream); + if (ret < 0) + goto out; ret = soc_compr_components_open(cstream, &component); if (ret < 0) @@ -178,15 +172,9 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) goto out; } - if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) { - ret = cpu_dai->driver->cops->startup(cstream, cpu_dai); - if (ret < 0) { - dev_err(cpu_dai->dev, - "Compress ASoC: can't open interface %s: %d\n", - cpu_dai->name, ret); - goto out; - } - } + ret = snd_soc_dai_compr_startup(cpu_dai, cstream); + if (ret < 0) + goto out; ret = soc_compr_components_open(cstream, &component); if (ret < 0) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 2bc452fe02ff..5c88f80b781d 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -504,3 +504,16 @@ int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, return 0; } + +int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->startup) + ret = dai->driver->cops->startup(cstream, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup); From 2b25f81d43b764142699a430da0ca57ffcb33cc2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:28 +0900 Subject: [PATCH 139/428] ASoC: soc-dai: add snd_soc_dai_compr_shutdown() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_shutdown(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87o8rhssj3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-compress.c | 12 ++++-------- sound/soc/soc-dai.c | 9 +++++++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index deb99b1469b4..abf4ad25ce68 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -172,6 +172,8 @@ int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, struct snd_compr_stream *cstream); +void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 7960270f5e67..af74fb7959b9 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -114,8 +114,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) machine_err: soc_compr_components_free(cstream, component); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) - cpu_dai->driver->cops->shutdown(cstream, cpu_dai); + snd_soc_dai_compr_shutdown(cpu_dai, cstream); out: mutex_unlock(&rtd->card->pcm_mutex); pm_err: @@ -204,8 +203,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) machine_err: soc_compr_components_free(cstream, component); open_err: - if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) - cpu_dai->driver->cops->shutdown(cstream, cpu_dai); + snd_soc_dai_compr_shutdown(cpu_dai, cstream); out: dpcm_path_put(&list); be_err: @@ -244,8 +242,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) soc_compr_components_free(cstream, NULL); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) - cpu_dai->driver->cops->shutdown(cstream, cpu_dai); + snd_soc_dai_compr_shutdown(cpu_dai, cstream); snd_soc_dapm_stream_stop(rtd, stream); @@ -301,8 +298,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) soc_compr_components_free(cstream, NULL); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) - cpu_dai->driver->cops->shutdown(cstream, cpu_dai); + snd_soc_dai_compr_shutdown(cpu_dai, cstream); mutex_unlock(&fe->card->mutex); return 0; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 5c88f80b781d..d5cb8b0853a7 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -517,3 +517,12 @@ int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup); + +void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream) +{ + if (dai->driver->cops && + dai->driver->cops->shutdown) + dai->driver->cops->shutdown(cstream, dai); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); From eb08411bdf48cff69f7226c86a97fba1ef5045e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:32 +0900 Subject: [PATCH 140/428] ASoC: soc-dai: add snd_soc_dai_compr_trigger() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_trigger(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87mu71ssiz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-compress.c | 13 ++++++------- sound/soc/soc-dai.c | 13 +++++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index abf4ad25ce68..ae04575ed8bc 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -174,6 +174,8 @@ int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, struct snd_compr_stream *cstream); void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, struct snd_compr_stream *cstream); +int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, int cmd); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index af74fb7959b9..b05305a4d86c 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -338,8 +338,9 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) if (ret < 0) goto out; - if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) - cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai); + ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); + if (ret < 0) + goto out; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -372,11 +373,9 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) { - ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai); - if (ret < 0) - goto out; - } + ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); + if (ret < 0) + goto out; ret = soc_compr_components_trigger(cstream, cmd); if (ret < 0) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index d5cb8b0853a7..844b52528174 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -526,3 +526,16 @@ void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, dai->driver->cops->shutdown(cstream, dai); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); + +int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, int cmd) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->trigger) + ret = dai->driver->cops->trigger(cstream, cmd, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger); From 8dfedafb5c711b5a13c938e06e8143540f773ecf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:36 +0900 Subject: [PATCH 141/428] ASoC: soc-dai: add snd_soc_dai_compr_set_params() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_set_params(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87lfmlssiv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 16 ++++++---------- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index ae04575ed8bc..1a2ef3002b6a 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -176,6 +176,9 @@ void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, struct snd_compr_stream *cstream); int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, int cmd); +int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_params *params); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index b05305a4d86c..13b5c7ad82c0 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -443,11 +443,9 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, * that these callbacks will configure everything for this compress * path, like configuring a PCM port for a CODEC. */ - if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) { - ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai); - if (ret < 0) - goto err; - } + ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); + if (ret < 0) + goto err; ret = soc_compr_components_set_params(cstream, params); if (ret < 0) @@ -513,11 +511,9 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, if (ret < 0) goto out; - if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) { - ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai); - if (ret < 0) - goto out; - } + ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); + if (ret < 0) + goto out; ret = soc_compr_components_set_params(cstream, params); if (ret < 0) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 844b52528174..44e754f03947 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -539,3 +539,17 @@ int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger); + +int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_params *params) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->set_params) + ret = dai->driver->cops->set_params(cstream, params, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params); From adbef5432666e20616263792d13cab80d57d9d5f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:40 +0900 Subject: [PATCH 142/428] ASoC: soc-dai: add snd_soc_dai_compr_get_params() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_get_params(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87k125ssir.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 8 +++----- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1a2ef3002b6a..ba48dc9d0a73 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -179,6 +179,9 @@ int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_params *params); +int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_codec *params); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 13b5c7ad82c0..48e39c35ef08 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -544,11 +544,9 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) { - ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai); - if (ret < 0) - goto err; - } + ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); + if (ret < 0) + goto err; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 44e754f03947..c06e510855f2 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -553,3 +553,17 @@ int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params); + +int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_codec *params) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->get_params) + ret = dai->driver->cops->get_params(cstream, params, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params); From 53294353a05ceaa6a107e8c1c300af63c89c8e50 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:45 +0900 Subject: [PATCH 143/428] ASoC: soc-dai: add snd_soc_dai_compr_ack() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_ack(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87imhpssim.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 8 +++----- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index ba48dc9d0a73..16dc9248f7f0 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -182,6 +182,9 @@ int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_codec *params); +int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + size_t bytes); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 48e39c35ef08..945e664c78b2 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -618,11 +618,9 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) { - ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai); - if (ret < 0) - goto err; - } + ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); + if (ret < 0) + goto err; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index c06e510855f2..bf52ecb26c0e 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -567,3 +567,17 @@ int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params); + +int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + size_t bytes) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->ack) + ret = dai->driver->cops->ack(cstream, bytes, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); From ed38cc5909e72e30815f72e73cba34a3dbbb5494 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:49 +0900 Subject: [PATCH 144/428] ASoC: soc-dai: add snd_soc_dai_compr_pointer() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_pointer(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87h7x9ssii.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 7 ++++--- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 16dc9248f7f0..8101ec030e63 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -185,6 +185,9 @@ int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, size_t bytes); +int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 945e664c78b2..93b2c88bb1eb 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -648,8 +648,9 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer) - cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai); + ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); + if (ret < 0) + goto out; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || @@ -660,7 +661,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, component, cstream, tstamp); break; } - +out: mutex_unlock(&rtd->card->pcm_mutex); return ret; } diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index bf52ecb26c0e..89fcf194c45e 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -581,3 +581,17 @@ int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); + +int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->pointer) + ret = dai->driver->cops->pointer(cstream, tstamp, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer); From 88b3a7dfe999b3e28f65be69787a1fd97b742b4f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:54 +0900 Subject: [PATCH 145/428] ASoC: soc-dai: add snd_soc_dai_compr_set_metadata() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_set_metadata(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87ftctssid.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 8 +++----- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 8101ec030e63..d21a2a33b7bc 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -188,6 +188,9 @@ int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_tstamp *tstamp); +int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 93b2c88bb1eb..7dd790c6f48f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -697,11 +697,9 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream, struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret; - if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) { - ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai); - if (ret < 0) - return ret; - } + ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata); + if (ret < 0) + return ret; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 89fcf194c45e..88990792fe49 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -595,3 +595,17 @@ int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer); + +int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->set_metadata) + ret = dai->driver->cops->set_metadata(cstream, metadata, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata); From 94d7281993a7933bf60ea733eeb8a8bad429bf1c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:59 +0900 Subject: [PATCH 146/428] ASoC: soc-dai: add snd_soc_dai_compr_get_metadata() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_get_metadata(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87eesdssi8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 8 +++----- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index d21a2a33b7bc..2a0a5af1c1ae 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -191,6 +191,9 @@ int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_metadata *metadata); +int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 7dd790c6f48f..def3ae78b4a7 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -723,11 +723,9 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret; - if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) { - ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai); - if (ret < 0) - return ret; - } + ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata); + if (ret < 0) + return ret; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 88990792fe49..8e5fe012aa1d 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -609,3 +609,17 @@ int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata); + +int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->get_metadata) + ret = dai->driver->cops->get_metadata(cstream, metadata, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata); From be16a0f0dc8fab8e25d9cdbeb4f8f28afc9186d2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 28 Apr 2020 23:47:31 +0200 Subject: [PATCH 147/428] ASoC: component: suppress uninitialized-variable warning Old versions of gcc (tested on gcc-4.8) produce a warning for correct code: sound/soc/soc-compress.c: In function 'soc_compr_open': sound/soc/soc-compress.c:75:28: error: 'component' is used uninitialized in this function [-Werror=uninitialized] struct snd_soc_component *component, *save = NULL; Change the for_each_rtd_components() macro to ensure 'component' gets initialized to a value the compiler does not complain about. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20200428214754.3925368-1-arnd@arndb.de 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 7411546dda9f..1288a87f9ccb 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1179,7 +1179,7 @@ struct snd_soc_pcm_runtime { #define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->num_cpus] #define for_each_rtd_components(rtd, i, component) \ - for ((i) = 0; \ + for ((i) = 0, component = NULL; \ ((i) < rtd->num_components) && ((component) = rtd->components[i]);\ (i)++) #define for_each_rtd_cpu_dais(rtd, i, dai) \ From ee2cbe06935bfa58f1fe07dc2a2283945f4b97dc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 28 Apr 2020 23:26:59 +0200 Subject: [PATCH 148/428] ASoC: codecs: wm97xx: fix ac97 dependency A recent build fix got the dependency slightly wrong, breaking builds with CONFIG_AC97_BUS_NEW: WARNING: unmet direct dependencies detected for SND_SOC_WM9713 Depends on [n]: SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_AC97_BUS [=n] Selected by [m]: - SND_SOC_ZYLONITE [=m] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_PXA2XX_SOC [=m] && MACH_ZYLONITE [=y] && AC97_BUS [=n]=n WARNING: unmet direct dependencies detected for SND_SOC_WM9712 Depends on [n]: SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_AC97_BUS [=n] Selected by [m]: - SND_PXA2XX_SOC_EM_X270 [=m] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_PXA2XX_SOC [=m] && (MACH_EM_X270 [=n] || MACH_EXEDA [=n] || MACH_CM_X300 [=y]) && AC97_BUS [=n]=n Change the dependency to allow either version of the AC97 library code. Fixes: 5a309875787d ("ASoC: Fix SND_SOC_ALL_CODECS imply ac97 fallout") Signed-off-by: Arnd Bergmann Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20200428212721.2877627-1-arnd@arndb.de Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 81341c70d563..2531a4fb59e2 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1621,19 +1621,19 @@ config SND_SOC_WM9090 config SND_SOC_WM9705 tristate - depends on SND_SOC_AC97_BUS + depends on SND_SOC_AC97_BUS || AC97_BUS_NEW select REGMAP_AC97 select AC97_BUS_COMPAT if AC97_BUS_NEW config SND_SOC_WM9712 tristate - depends on SND_SOC_AC97_BUS + depends on SND_SOC_AC97_BUS || AC97_BUS_NEW select REGMAP_AC97 select AC97_BUS_COMPAT if AC97_BUS_NEW config SND_SOC_WM9713 tristate - depends on SND_SOC_AC97_BUS + depends on SND_SOC_AC97_BUS || AC97_BUS_NEW select REGMAP_AC97 select AC97_BUS_COMPAT if AC97_BUS_NEW From 77be181e2c8e435692424ff2e5ee3d0380cabb90 Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Wed, 29 Apr 2020 17:00:02 +0800 Subject: [PATCH 149/428] ASoc: nau8810: add AUX related dapm widgets and routes This patch implements the following features: - AUX input for recording. - An input AUX output to SPK/MOUT. Signed-off-by: Seven Lee Link: https://lore.kernel.org/r/20200429090002.28556-1-wtli@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8810.c | 35 ++++++++++++++++++++++++++++++++++- sound/soc/codecs/nau8810.h | 8 ++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c index de26758c30a8..efe9fb3fb225 100644 --- a/sound/soc/codecs/nau8810.c +++ b/sound/soc/codecs/nau8810.c @@ -355,6 +355,8 @@ static const struct snd_kcontrol_new nau8810_snd_controls[] = { /* Speaker Output Mixer */ static const struct snd_kcontrol_new nau8810_speaker_mixer_controls[] = { + SOC_DAPM_SINGLE("AUX Bypass Switch", NAU8810_REG_SPKMIX, + NAU8810_AUXSPK_SFT, 1, 0), SOC_DAPM_SINGLE("Line Bypass Switch", NAU8810_REG_SPKMIX, NAU8810_BYPSPK_SFT, 1, 0), SOC_DAPM_SINGLE("PCM Playback Switch", NAU8810_REG_SPKMIX, @@ -363,6 +365,8 @@ static const struct snd_kcontrol_new nau8810_speaker_mixer_controls[] = { /* Mono Output Mixer */ static const struct snd_kcontrol_new nau8810_mono_mixer_controls[] = { + SOC_DAPM_SINGLE("AUX Bypass Switch", NAU8810_REG_MONOMIX, + NAU8810_AUXMOUT_SFT, 1, 0), SOC_DAPM_SINGLE("Line Bypass Switch", NAU8810_REG_MONOMIX, NAU8810_BYPMOUT_SFT, 1, 0), SOC_DAPM_SINGLE("PCM Playback Switch", NAU8810_REG_MONOMIX, @@ -371,6 +375,8 @@ static const struct snd_kcontrol_new nau8810_mono_mixer_controls[] = { /* PGA Mute */ static const struct snd_kcontrol_new nau8810_pgaboost_mixer_controls[] = { + SOC_DAPM_SINGLE("AUX PGA Switch", NAU8810_REG_ADCBOOST, + NAU8810_AUXBSTGAIN_SFT, 0x7, 0), SOC_DAPM_SINGLE("PGA Mute Switch", NAU8810_REG_PGAGAIN, NAU8810_PGAMT_SFT, 1, 1), SOC_DAPM_SINGLE("PMIC PGA Switch", NAU8810_REG_ADCBOOST, @@ -379,6 +385,8 @@ static const struct snd_kcontrol_new nau8810_pgaboost_mixer_controls[] = { /* Input PGA */ static const struct snd_kcontrol_new nau8810_inpga[] = { + SOC_DAPM_SINGLE("AUX Switch", NAU8810_REG_INPUT_SIGNAL, + NAU8810_AUXPGA_SFT, 1, 0), SOC_DAPM_SINGLE("MicN Switch", NAU8810_REG_INPUT_SIGNAL, NAU8810_NMICPGA_SFT, 1, 0), SOC_DAPM_SINGLE("MicP Switch", NAU8810_REG_INPUT_SIGNAL, @@ -401,6 +409,23 @@ static int check_mclk_select_pll(struct snd_soc_dapm_widget *source, return (value & NAU8810_CLKM_MASK); } +static int check_mic_enabled(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 nau8810 *nau8810 = snd_soc_component_get_drvdata(component); + unsigned int value; + + regmap_read(nau8810->regmap, NAU8810_REG_INPUT_SIGNAL, &value); + if (value & NAU8810_PMICPGA_EN || value & NAU8810_NMICPGA_EN) + return 1; + regmap_read(nau8810->regmap, NAU8810_REG_ADCBOOST, &value); + if (value & NAU8810_PMICBSTGAIN_MASK) + return 1; + return 0; +} + static const struct snd_soc_dapm_widget nau8810_dapm_widgets[] = { SND_SOC_DAPM_MIXER("Speaker Mixer", NAU8810_REG_POWER3, NAU8810_SPKMX_EN_SFT, 0, &nau8810_speaker_mixer_controls[0], @@ -425,6 +450,8 @@ static const struct snd_soc_dapm_widget nau8810_dapm_widgets[] = { SND_SOC_DAPM_MIXER("Input Boost Stage", NAU8810_REG_POWER2, NAU8810_BST_EN_SFT, 0, nau8810_pgaboost_mixer_controls, ARRAY_SIZE(nau8810_pgaboost_mixer_controls)), + SND_SOC_DAPM_PGA("AUX Input", NAU8810_REG_POWER1, + NAU8810_AUX_EN_SFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("Mic Bias", NAU8810_REG_POWER1, NAU8810_MICBIAS_EN_SFT, 0, NULL, 0), @@ -434,6 +461,7 @@ static const struct snd_soc_dapm_widget nau8810_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("Digital Loopback", SND_SOC_NOPM, 0, 0, &nau8810_loopback), + SND_SOC_DAPM_INPUT("AUX"), SND_SOC_DAPM_INPUT("MICN"), SND_SOC_DAPM_INPUT("MICP"), SND_SOC_DAPM_OUTPUT("MONOOUT"), @@ -445,10 +473,12 @@ static const struct snd_soc_dapm_route nau8810_dapm_routes[] = { {"DAC", NULL, "PLL", check_mclk_select_pll}, /* Mono output mixer */ + {"Mono Mixer", "AUX Bypass Switch", "AUX Input"}, {"Mono Mixer", "PCM Playback Switch", "DAC"}, {"Mono Mixer", "Line Bypass Switch", "Input Boost Stage"}, /* Speaker output mixer */ + {"Speaker Mixer", "AUX Bypass Switch", "AUX Input"}, {"Speaker Mixer", "PCM Playback Switch", "DAC"}, {"Speaker Mixer", "Line Bypass Switch", "Input Boost Stage"}, @@ -463,13 +493,16 @@ static const struct snd_soc_dapm_route nau8810_dapm_routes[] = { /* Input Boost Stage */ {"ADC", NULL, "Input Boost Stage"}, {"ADC", NULL, "PLL", check_mclk_select_pll}, + {"Input Boost Stage", "AUX PGA Switch", "AUX Input"}, {"Input Boost Stage", "PGA Mute Switch", "Input PGA"}, {"Input Boost Stage", "PMIC PGA Switch", "MICP"}, /* Input PGA */ - {"Input PGA", NULL, "Mic Bias"}, + {"Input PGA", NULL, "Mic Bias", check_mic_enabled}, + {"Input PGA", "AUX Switch", "AUX Input"}, {"Input PGA", "MicN Switch", "MICN"}, {"Input PGA", "MicP Switch", "MICP"}, + {"AUX Input", NULL, "AUX"}, /* Digital Looptack */ {"Digital Loopback", "Switch", "ADC"}, diff --git a/sound/soc/codecs/nau8810.h b/sound/soc/codecs/nau8810.h index 1ada31883dc6..6a7cacbe044a 100644 --- a/sound/soc/codecs/nau8810.h +++ b/sound/soc/codecs/nau8810.h @@ -69,6 +69,7 @@ /* NAU8810_REG_POWER1 (0x1) */ #define NAU8810_DCBUF_EN (0x1 << 8) +#define NAU8810_AUX_EN_SFT 6 #define NAU8810_PLL_EN_SFT 5 #define NAU8810_MICBIAS_EN_SFT 4 #define NAU8810_ABIAS_EN (0x1 << 3) @@ -228,7 +229,10 @@ /* NAU8810_REG_INPUT_SIGNAL (0x2C) */ #define NAU8810_PMICPGA_SFT 0 +#define NAU8810_PMICPGA_EN (0x1 << NAU8810_PMICPGA_SFT) #define NAU8810_NMICPGA_SFT 1 +#define NAU8810_NMICPGA_EN (0x1 << NAU8810_NMICPGA_SFT) +#define NAU8810_AUXPGA_SFT 2 /* NAU8810_REG_PGAGAIN (0x2D) */ #define NAU8810_PGAGAIN_SFT 0 @@ -236,12 +240,15 @@ #define NAU8810_PGAZC_SFT 7 /* NAU8810_REG_ADCBOOST (0x2F) */ +#define NAU8810_AUXBSTGAIN_SFT 0 #define NAU8810_PMICBSTGAIN_SFT 4 +#define NAU8810_PMICBSTGAIN_MASK (0x7 << NAU8810_PMICBSTGAIN_SFT) #define NAU8810_PGABST_SFT 8 /* NAU8810_REG_SPKMIX (0x32) */ #define NAU8810_DACSPK_SFT 0 #define NAU8810_BYPSPK_SFT 1 +#define NAU8810_AUXSPK_SFT 5 /* NAU8810_REG_SPKGAIN (0x36) */ #define NAU8810_SPKGAIN_SFT 0 @@ -251,6 +258,7 @@ /* NAU8810_REG_MONOMIX (0x38) */ #define NAU8810_DACMOUT_SFT 0 #define NAU8810_BYPMOUT_SFT 1 +#define NAU8810_AUXMOUT_SFT 2 #define NAU8810_MOUTMXMT_SFT 6 From da33574f7f1c110ec58ea43251a9a85801d6e015 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Wed, 29 Apr 2020 17:38:23 +0800 Subject: [PATCH 150/428] ASoC: mxs-saif: Fix unused assignment Delete unused initialized value, because 'ret' will be assigined by the function of_alias_get_id(). Signed-off-by: Zhang Shengju Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200429093823.1372-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 64c095b91d35..07f8cf9980e3 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -733,7 +733,7 @@ static int mxs_saif_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mxs_saif *saif; - int irq, ret = 0; + int irq, ret; struct device_node *master; saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL); From 25cba461989c3ebf7236ec17a0ac3949dc80ce8c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 29 Apr 2020 21:28:05 +0800 Subject: [PATCH 151/428] ALSA: seq: oss: remove unused inline function snd_seq_oss_timer_is_realtime There's no callers in-tree. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200429132805.18712-1-yuehaibing@huawei.com Signed-off-by: Takashi Iwai --- sound/core/seq/oss/seq_oss_timer.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sound/core/seq/oss/seq_oss_timer.h b/sound/core/seq/oss/seq_oss_timer.h index 2d86125b5d0f..dee190b4ec6b 100644 --- a/sound/core/seq/oss/seq_oss_timer.h +++ b/sound/core/seq/oss/seq_oss_timer.h @@ -44,14 +44,4 @@ snd_seq_oss_timer_cur_tick(struct seq_oss_timer *timer) return timer->cur_tick; } - -/* - * is realtime event? - */ -static inline int -snd_seq_oss_timer_is_realtime(struct seq_oss_timer *timer) -{ - return timer->realtime; -} - #endif From 087e3900a060cfc8516e02ea83fe6122da490d23 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 28 Apr 2020 23:28:08 +0200 Subject: [PATCH 152/428] ASoC: fsl_easrc: mark PM functions __maybe_unused ifdefs are hard, and in this driver the suspend/resume functions are the only callers of some other helpers that trigger a harmless warning when CONFIG_PM is disabled: sound/soc/fsl/fsl_easrc.c:1807:12: warning: 'fsl_easrc_get_firmware' defined but not used [-Wunused-function] 1807 | static int fsl_easrc_get_firmware(struct fsl_asrc *easrc) | ^~~~~~~~~~~~~~~~~~~~~~ sound/soc/fsl/fsl_easrc.c:303:12: warning: 'fsl_easrc_resampler_config' defined but not used [-Wunused-function] 303 | static int fsl_easrc_resampler_config(struct fsl_asrc *easrc) | ^~~~~~~~~~~~~~~~~~~~~~~~~~ Remove the #ifdef and just mark the callers as __maybe_unused to suppress the warnings altogether. Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers") Signed-off-by: Arnd Bergmann Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20200428212847.2926376-1-arnd@arndb.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 20326bffab64..c6b5eb2d2af7 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1997,8 +1997,7 @@ static int fsl_easrc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int fsl_easrc_runtime_suspend(struct device *dev) +static __maybe_unused int fsl_easrc_runtime_suspend(struct device *dev) { struct fsl_asrc *easrc = dev_get_drvdata(dev); struct fsl_easrc_priv *easrc_priv = easrc->private; @@ -2015,7 +2014,7 @@ static int fsl_easrc_runtime_suspend(struct device *dev) return 0; } -static int fsl_easrc_runtime_resume(struct device *dev) +static __maybe_unused int fsl_easrc_runtime_resume(struct device *dev) { struct fsl_asrc *easrc = dev_get_drvdata(dev); struct fsl_easrc_priv *easrc_priv = easrc->private; @@ -2094,7 +2093,6 @@ disable_mem_clk: clk_disable_unprepare(easrc->mem_clk); return ret; } -#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_easrc_pm_ops = { SET_RUNTIME_PM_OPS(fsl_easrc_runtime_suspend, From fd443a20c2f0950f3c31765a08f7dd49b3bc69cb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 28 Apr 2020 23:46:14 +0200 Subject: [PATCH 153/428] ASoC: rt5682: fix I2C/Soundwire dependencies If one of the two is a loadable module, the combined driver must not be built-in: aarch64-linux-ld: sound/soc/codecs/rt5682.o: in function `rt5682_sdw_hw_free': rt5682.c:(.text+0xb34): undefined reference to `sdw_stream_remove_slave' aarch64-linux-ld: sound/soc/codecs/rt5682.o: in function `rt5682_sdw_hw_params': rt5682.c:(.text+0xe78): undefined reference to `sdw_stream_add_slave' In particular, the soundwire driver must not be built-in if CONFIG_I2C=m. Fixes: 5549ea647997 ("ASoC: rt5682: fix unmet dependencies") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20200428214642.3925004-1-arnd@arndb.de Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 2531a4fb59e2..44b8c4cde4f3 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1137,10 +1137,13 @@ config SND_SOC_RT5677_SPI config SND_SOC_RT5682 tristate depends on I2C || SOUNDWIRE + depends on SOUNDWIRE || !SOUNDWIRE + depends on I2C || !I2C config SND_SOC_RT5682_SDW tristate "Realtek RT5682 Codec - SDW" depends on SOUNDWIRE + depends on I2C || !I2C select SND_SOC_RT5682 select REGMAP_SOUNDWIRE From 79149fb835d762493db6b8b545527069d592d51b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 1 Apr 2020 09:00:04 +0900 Subject: [PATCH 154/428] ASoC: dt-bindings: simple-card: switch to yaml base Documentation This patch switches from .txt base to .yaml base Document. Signed-off-by: Kuninori Morimoto Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/87sghovzwb.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/simple-card.txt | 351 ------------- .../bindings/sound/simple-card.yaml | 484 ++++++++++++++++++ 2 files changed, 484 insertions(+), 351 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/simple-card.txt create mode 100644 Documentation/devicetree/bindings/sound/simple-card.yaml diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt deleted file mode 100644 index 79954cd6e37b..000000000000 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ /dev/null @@ -1,351 +0,0 @@ -Simple-Card: - -Simple-Card specifies audio DAI connections of SoC <-> codec. - -Required properties: - -- compatible : "simple-audio-card" - -Optional properties: - -- simple-audio-card,name : User specified audio sound card name, one string - property. -- simple-audio-card,widgets : Please refer to widgets.txt. -- simple-audio-card,routing : A list of the connections between audio components. - Each entry is a pair of strings, the first being the - connection's sink, the second being the connection's - source. -- simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec - mclk. When defined, mclk-fs property defined in - dai-link sub nodes are ignored. -- simple-audio-card,hp-det-gpio : Reference to GPIO that signals when - headphones are attached. -- simple-audio-card,mic-det-gpio : Reference to GPIO that signals when - a microphone is attached. -- simple-audio-card,aux-devs : List of phandles pointing to auxiliary devices, such - as amplifiers, to be added to the sound card. -- simple-audio-card,pin-switches : List of strings containing the widget names for - which pin switches must be created. - -Optional subnodes: - -- simple-audio-card,dai-link : Container for dai-link level - properties and the CPU and CODEC - sub-nodes. This container may be - omitted when the card has only one - DAI link. See the examples and the - section below. - -Dai-link subnode properties and subnodes: - -If dai-link subnode is omitted and the subnode properties are directly -under "sound"-node the subnode property and subnode names have to be -prefixed with "simple-audio-card,"-prefix. - -Required dai-link subnodes: - -- cpu : CPU sub-node -- codec : CODEC sub-node - -Optional dai-link subnode properties: - -- format : CPU/CODEC common audio format. - "i2s", "right_j", "left_j" , "dsp_a" - "dsp_b", "ac97", "pdm", "msb", "lsb" -- frame-master : Indicates dai-link frame master. - phandle to a cpu or codec subnode. -- bitclock-master : Indicates dai-link bit clock master. - phandle to a cpu or codec subnode. -- bitclock-inversion : bool property. Add this if the - dai-link uses bit clock inversion. -- frame-inversion : bool property. Add this if the - dai-link uses frame clock inversion. -- mclk-fs : Multiplication factor between stream - rate and codec mclk, applied only for - the dai-link. - -For backward compatibility the frame-master and bitclock-master -properties can be used as booleans in codec subnode to indicate if the -codec is the dai-link frame or bit clock master. In this case there -should be no dai-link node, the same properties should not be present -at sound-node level, and the bitclock-inversion and frame-inversion -properties should also be placed in the codec node if needed. - -Required CPU/CODEC subnodes properties: - -- sound-dai : phandle and port of CPU/CODEC - -Optional CPU/CODEC subnodes properties: - -- dai-tdm-slot-num : Please refer to tdm-slot.txt. -- dai-tdm-slot-width : Please refer to tdm-slot.txt. -- clocks / system-clock-frequency : specify subnode's clock if needed. - it can be specified via "clocks" if system has - clock node (= common clock), or "system-clock-frequency" - (if system doens't support common clock) - If a clock is specified, it is - enabled with clk_prepare_enable() - in dai startup() and disabled with - clk_disable_unprepare() in dai - shutdown(). - If a clock is specified and a - multiplication factor is given with - mclk-fs, the clock will be set to the - calculated mclk frequency when the - stream starts. -- system-clock-direction-out : specifies clock direction as 'out' on - initialization. It is useful for some aCPUs with - fixed clocks. - -------------------------------------------- -Example 1 - single DAI link: -------------------------------------------- - -sound { - compatible = "simple-audio-card"; - simple-audio-card,name = "VF610-Tower-Sound-Card"; - simple-audio-card,format = "left_j"; - simple-audio-card,bitclock-master = <&dailink0_master>; - simple-audio-card,frame-master = <&dailink0_master>; - simple-audio-card,widgets = - "Microphone", "Microphone Jack", - "Headphone", "Headphone Jack", - "Speaker", "External Speaker"; - simple-audio-card,routing = - "MIC_IN", "Microphone Jack", - "Headphone Jack", "HP_OUT", - "External Speaker", "LINE_OUT"; - - simple-audio-card,cpu { - sound-dai = <&sh_fsi2 0>; - }; - - dailink0_master: simple-audio-card,codec { - sound-dai = <&ak4648>; - clocks = <&osc>; - }; -}; - -&i2c0 { - ak4648: ak4648@12 { - #sound-dai-cells = <0>; - compatible = "asahi-kasei,ak4648"; - reg = <0x12>; - }; -}; - -sh_fsi2: sh_fsi2@ec230000 { - #sound-dai-cells = <1>; - compatible = "renesas,sh_fsi2"; - reg = <0xec230000 0x400>; - interrupt-parent = <&gic>; - interrupts = <0 146 0x4>; -}; - -------------------------------------------- -Example 2 - many DAI links: -------------------------------------------- - -sound { - compatible = "simple-audio-card"; - simple-audio-card,name = "Cubox Audio"; - - simple-audio-card,dai-link@0 { /* I2S - HDMI */ - reg = <0>; - format = "i2s"; - cpu { - sound-dai = <&audio1 0>; - }; - codec { - sound-dai = <&tda998x 0>; - }; - }; - - simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */ - reg = <1>; - cpu { - sound-dai = <&audio1 1>; - }; - codec { - sound-dai = <&tda998x 1>; - }; - }; - - simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */ - reg = <2>; - cpu { - sound-dai = <&audio1 1>; - }; - codec { - sound-dai = <&spdif_codec>; - }; - }; -}; - -------------------------------------------- -Example 3 - route audio from IMX6 SSI2 through TLV320DAC3100 codec -through TPA6130A2 amplifier to headphones: -------------------------------------------- - -&i2c0 { - codec: tlv320dac3100@18 { - compatible = "ti,tlv320dac3100"; - ... - } - - amp: tpa6130a2@60 { - compatible = "ti,tpa6130a2"; - ... - } -} - -sound { - compatible = "simple-audio-card"; - ... - simple-audio-card,widgets = - "Headphone", "Headphone Jack"; - simple-audio-card,routing = - "Headphone Jack", "HPLEFT", - "Headphone Jack", "HPRIGHT", - "LEFTIN", "HPL", - "RIGHTIN", "HPR"; - simple-audio-card,aux-devs = <&>; - simple-audio-card,cpu { - sound-dai = <&ssi2>; - }; - simple-audio-card,codec { - sound-dai = <&codec>; - clocks = ... - }; -}; - -------------------------------------------- -Example 4. Sampling Rate Conversion -------------------------------------------- - -sound { - compatible = "simple-audio-card"; - - simple-audio-card,name = "rsnd-ak4643"; - simple-audio-card,format = "left_j"; - simple-audio-card,bitclock-master = <&sndcodec>; - simple-audio-card,frame-master = <&sndcodec>; - - simple-audio-card,convert-rate = <48000>; - - simple-audio-card,prefix = "ak4642"; - simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", - "DAI0 Capture", "ak4642 Capture"; - - sndcpu: simple-audio-card,cpu { - sound-dai = <&rcar_sound>; - }; - - sndcodec: simple-audio-card,codec { - sound-dai = <&ak4643>; - system-clock-frequency = <11289600>; - }; -}; - -------------------------------------------- -Example 5. 2 CPU 1 Codec (Mixing) -------------------------------------------- -sound { - compatible = "simple-audio-card"; - - simple-audio-card,name = "rsnd-ak4643"; - simple-audio-card,format = "left_j"; - simple-audio-card,bitclock-master = <&dpcmcpu>; - simple-audio-card,frame-master = <&dpcmcpu>; - - simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", - "ak4642 Playback", "DAI1 Playback"; - - dpcmcpu: cpu@0 { - sound-dai = <&rcar_sound 0>; - }; - - cpu@1 { - sound-dai = <&rcar_sound 1>; - }; - - codec { - prefix = "ak4642"; - sound-dai = <&ak4643>; - clocks = <&audio_clock>; - }; -}; - -------------------------------------------- -Example 6 - many DAI links with DPCM: -------------------------------------------- - -CPU0 ------ ak4613 -CPU1 ------ PCM3168A-p /* DPCM 1ch/2ch */ -CPU2 --/ /* DPCM 3ch/4ch */ -CPU3 --/ /* DPCM 5ch/6ch */ -CPU4 --/ /* DPCM 7ch/8ch */ -CPU5 ------ PCM3168A-c - -sound { - compatible = "simple-audio-card"; - - simple-audio-card,routing = - "pcm3168a Playback", "DAI1 Playback", - "pcm3168a Playback", "DAI2 Playback", - "pcm3168a Playback", "DAI3 Playback", - "pcm3168a Playback", "DAI4 Playback"; - - simple-audio-card,dai-link@0 { - format = "left_j"; - bitclock-master = <&sndcpu0>; - frame-master = <&sndcpu0>; - - sndcpu0: cpu { - sound-dai = <&rcar_sound 0>; - }; - codec { - sound-dai = <&ak4613>; - }; - }; - simple-audio-card,dai-link@1 { - format = "i2s"; - bitclock-master = <&sndcpu1>; - frame-master = <&sndcpu1>; - - convert-channels = <8>; /* TDM Split */ - - sndcpu1: cpu@0 { - sound-dai = <&rcar_sound 1>; - }; - cpu@1 { - sound-dai = <&rcar_sound 2>; - }; - cpu@2 { - sound-dai = <&rcar_sound 3>; - }; - cpu@3 { - sound-dai = <&rcar_sound 4>; - }; - codec { - mclk-fs = <512>; - prefix = "pcm3168a"; - dai-tdm-slot-num = <8>; - sound-dai = <&pcm3168a 0>; - }; - }; - simple-audio-card,dai-link@2 { - format = "i2s"; - bitclock-master = <&sndcpu2>; - frame-master = <&sndcpu2>; - - sndcpu2: cpu { - sound-dai = <&rcar_sound 5>; - }; - codec { - mclk-fs = <512>; - prefix = "pcm3168a"; - sound-dai = <&pcm3168a 1>; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml new file mode 100644 index 000000000000..cb2bb5fac0e1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/simple-card.yaml @@ -0,0 +1,484 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/simple-card.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Simple Audio Card Driver Device Tree Bindings + +maintainers: + - Kuninori Morimoto + +definitions: + + frame-master: + description: Indicates dai-link frame master. + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle-array + - maxItems: 1 + + bitclock-master: + description: Indicates dai-link bit clock master + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle-array + - maxItems: 1 + + frame-inversion: + description: dai-link uses frame clock inversion + $ref: /schemas/types.yaml#/definitions/flag + + bitclock-inversion: + description: dai-link uses bit clock inversion + $ref: /schemas/types.yaml#/definitions/flag + + dai-tdm-slot-num: + description: see tdm-slot.txt. + $ref: /schemas/types.yaml#/definitions/uint32 + + dai-tdm-slot-width: + description: see tdm-slot.txt. + $ref: /schemas/types.yaml#/definitions/uint32 + + system-clock-frequency: + description: | + If a clock is specified and a multiplication factor is given with + mclk-fs, the clock will be set to the calculated mclk frequency + when the stream starts. + $ref: /schemas/types.yaml#/definitions/uint32 + + system-clock-direction-out: + description: | + specifies clock direction as 'out' on initialization. + It is useful for some aCPUs with fixed clocks. + $ref: /schemas/types.yaml#/definitions/flag + + mclk-fs: + description: | + Multiplication factor between stream rate and codec mclk. + When defined, mclk-fs property defined in dai-link sub nodes are ignored. + $ref: /schemas/types.yaml#/definitions/uint32 + + aux-devs: + description: | + List of phandles pointing to auxiliary devices, such + as amplifiers, to be added to the sound card. + $ref: /schemas/types.yaml#/definitions/phandle-array + + convert-rate: + description: CPU to Codec rate convert. + $ref: /schemas/types.yaml#/definitions/uint32 + + convert-channels: + description: CPU to Codec rate channels. + $ref: /schemas/types.yaml#/definitions/uint32 + + prefix: + description: "device name prefix" + $ref: /schemas/types.yaml#/definitions/string + + label: + maxItems: 1 + + routing: + description: | + A list of the connections between audio components. + Each entry is a pair of strings, the first being the + connection's sink, the second being the connection's source. + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + + widgets: + description: User specified audio sound widgets. + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + + pin-switches: + description: the widget names for which pin switches must be created. + $ref: /schemas/types.yaml#/definitions/string-array + + format: + description: audio format. + items: + enum: + - i2s + - right_j + - left_j + - dsp_a + - dsp_b + - ac97 + - pdm + - msb + - lsb + + dai: + type: object + properties: + sound-dai: + maxItems: 1 + + # common properties + mclk-fs: + $ref: "#/definitions/mclk-fs" + prefix: + $ref: "#/definitions/prefix" + frame-inversion: + $ref: "#/definitions/frame-inversion" + bitclock-inversion: + $ref: "#/definitions/bitclock-inversion" + frame-master: + $ref: /schemas/types.yaml#/definitions/flag + bitclock-master: + $ref: /schemas/types.yaml#/definitions/flag + + dai-tdm-slot-num: + $ref: "#/definitions/dai-tdm-slot-num" + dai-tdm-slot-width: + $ref: "#/definitions/dai-tdm-slot-width" + clocks: + maxItems: 1 + system-clock-frequency: + $ref: "#/definitions/system-clock-frequency" + system-clock-direction-out: + $ref: "#/definitions/system-clock-direction-out" + required: + - sound-dai + +properties: + compatible: + contains: + enum: + - simple-audio-card + - simple-scu-audio-card + + "#address-cells": + const: 1 + "#size-cells": + const: 0 + + label: + $ref: "#/definitions/label" + + simple-audio-card,name: + description: User specified audio sound card name. + $ref: /schemas/types.yaml#/definitions/string + +# use patternProperties to avoid naming "xxx,yyy" issue +patternProperties: + "^simple-audio-card,widgets$": + $ref: "#/definitions/widgets" + "^simple-audio-card,routing$": + $ref: "#/definitions/routing" + "^simple-audio-card,cpu(@[0-9a-f]+)?": + $ref: "#/definitions/dai" + "^simple-audio-card,codec(@[0-9a-f]+)?": + $ref: "#/definitions/dai" + + # common properties + "^simple-audio-card,frame-master$": + $ref: "#/definitions/frame-master" + "^simple-audio-card,bitclock-master$": + $ref: "#/definitions/bitclock-master" + "^simple-audio-card,frame-inversion$": + $ref: "#/definitions/frame-inversion" + "^simple-audio-card,bitclock-inversion$": + $ref: "#/definitions/bitclock-inversion" + "^simple-audio-card,format$": + $ref: "#/definitions/format" + "^simple-audio-card,mclk-fs$": + $ref: "#/definitions/mclk-fs" + "^simple-audio-card,aux-devs$": + $ref: "#/definitions/aux-devs" + "^simple-audio-card,convert-rate$": + $ref: "#/definitions/convert-rate" + "^simple-audio-card,convert-channels$": + $ref: "#/definitions/convert-channels" + "^simple-audio-card,prefix$": + $ref: "#/definitions/prefix" + "^simple-audio-card,pin-switches$": + $ref: "#/definitions/pin-switches" + "^simple-audio-card,hp-det-gpio$": + maxItems: 1 + "^simple-audio-card,mic-det-gpio$": + maxItems: 1 + + "^simple-audio-card,dai-link(@[0-9a-f]+)?$": + description: | + Container for dai-link level properties and the CPU and CODEC sub-nodes. + This container may be omitted when the card has only one DAI link. + type: object + properties: + reg: + maxItems: 1 + + # common properties + frame-master: + $ref: "#/definitions/frame-master" + bitclock-master: + $ref: "#/definitions/bitclock-master" + frame-inversion: + $ref: "#/definitions/frame-inversion" + bitclock-inversion: + $ref: "#/definitions/bitclock-inversion" + format: + $ref: "#/definitions/format" + mclk-fs: + $ref: "#/definitions/mclk-fs" + aux-devs: + $ref: "#/definitions/aux-devs" + convert-rate: + $ref: "#/definitions/convert-rate" + convert-channels: + $ref: "#/definitions/convert-channels" + prefix: + $ref: "#/definitions/prefix" + pin-switches: + $ref: "#/definitions/pin-switches" + hp-det-gpio: + maxItems: 1 + mic-det-gpio: + maxItems: 1 + + patternProperties: + "^cpu(@[0-9a-f]+)?": + $ref: "#/definitions/dai" + "^codec(@[0-9a-f]+)?": + $ref: "#/definitions/dai" + additionalProperties: false + +required: + - compatible + +additionalProperties: false + +examples: +#-------------------- +# single DAI link +#-------------------- + - | + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "VF610-Tower-Sound-Card"; + simple-audio-card,format = "left_j"; + simple-audio-card,bitclock-master = <&dailink0_master>; + simple-audio-card,frame-master = <&dailink0_master>; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Speaker", "External Speaker"; + simple-audio-card,routing = + "MIC_IN", "Microphone Jack", + "Headphone Jack", "HP_OUT", + "External Speaker", "LINE_OUT"; + + simple-audio-card,cpu { + sound-dai = <&sh_fsi2 0>; + }; + + dailink0_master: simple-audio-card,codec { + sound-dai = <&ak4648>; + clocks = <&osc>; + }; + }; + +#-------------------- +# Multi DAI links +#-------------------- + - | + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "Cubox Audio"; + + #address-cells = <1>; + #size-cells = <0>; + + simple-audio-card,dai-link@0 { /* I2S - HDMI */ + reg = <0>; + format = "i2s"; + cpu { + sound-dai = <&audio0>; + }; + codec { + sound-dai = <&tda998x0>; + }; + }; + + simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */ + reg = <1>; + cpu { + sound-dai = <&audio1>; + }; + codec { + sound-dai = <&tda998x1>; + }; + }; + + simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */ + reg = <2>; + cpu { + sound-dai = <&audio2>; + }; + codec { + sound-dai = <&spdif_codec>; + }; + }; + }; + +#-------------------- +# route audio from IMX6 SSI2 through TLV320DAC3100 codec +# through TPA6130A2 amplifier to headphones: +#-------------------- + - | + sound { + compatible = "simple-audio-card"; + + simple-audio-card,widgets = + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "Headphone Jack", "HPLEFT", + "Headphone Jack", "HPRIGHT", + "LEFTIN", "HPL", + "RIGHTIN", "HPR"; + simple-audio-card,aux-devs = <&>; + simple-audio-card,cpu { + sound-dai = <&ssi2>; + }; + simple-audio-card,codec { + sound-dai = <&codec>; + clocks = <&clocks>; + }; + }; + +#-------------------- +# Sampling Rate Conversion +#-------------------- + - | + sound { + compatible = "simple-audio-card"; + + simple-audio-card,name = "rsnd-ak4643"; + simple-audio-card,format = "left_j"; + simple-audio-card,bitclock-master = <&sndcodec>; + simple-audio-card,frame-master = <&sndcodec>; + + simple-audio-card,convert-rate = <48000>; + + simple-audio-card,prefix = "ak4642"; + simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", + "DAI0 Capture", "ak4642 Capture"; + + sndcpu: simple-audio-card,cpu { + sound-dai = <&rcar_sound>; + }; + + sndcodec: simple-audio-card,codec { + sound-dai = <&ak4643>; + system-clock-frequency = <11289600>; + }; + }; + +#-------------------- +# 2 CPU 1 Codec (Mixing) +#-------------------- + - | + sound { + compatible = "simple-audio-card"; + + simple-audio-card,name = "rsnd-ak4643"; + simple-audio-card,format = "left_j"; + simple-audio-card,bitclock-master = <&dpcmcpu>; + simple-audio-card,frame-master = <&dpcmcpu>; + + simple-audio-card,convert-rate = <48000>; + simple-audio-card,convert-channels = <2>; + + simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", + "ak4642 Playback", "DAI1 Playback"; + + dpcmcpu: simple-audio-card,cpu@0 { + sound-dai = <&rcar_sound 0>; + }; + + simple-audio-card,cpu@1 { + sound-dai = <&rcar_sound 1>; + }; + + simple-audio-card,codec { + prefix = "ak4642"; + sound-dai = <&ak4643>; + clocks = <&audio_clock>; + }; + }; + +#-------------------- +# Multi DAI links with DPCM: +# +# CPU0 ------ ak4613 +# CPU1 ------ PCM3168A-p /* DPCM 1ch/2ch */ +# CPU2 --/ /* DPCM 3ch/4ch */ +# CPU3 --/ /* DPCM 5ch/6ch */ +# CPU4 --/ /* DPCM 7ch/8ch */ +# CPU5 ------ PCM3168A-c +#-------------------- + - | + sound { + compatible = "simple-audio-card"; + + simple-audio-card,routing = + "pcm3168a Playback", "DAI1 Playback", + "pcm3168a Playback", "DAI2 Playback", + "pcm3168a Playback", "DAI3 Playback", + "pcm3168a Playback", "DAI4 Playback"; + + simple-audio-card,dai-link@0 { + format = "left_j"; + bitclock-master = <&sndcpu0>; + frame-master = <&sndcpu0>; + + sndcpu0: cpu { + sound-dai = <&rcar_sound 0>; + }; + codec { + sound-dai = <&ak4613>; + }; + }; + + simple-audio-card,dai-link@1 { + format = "i2s"; + bitclock-master = <&sndcpu1>; + frame-master = <&sndcpu1>; + + convert-channels = <8>; /* TDM Split */ + + sndcpu1: cpu@0 { + sound-dai = <&rcar_sound 1>; + }; + cpu@1 { + sound-dai = <&rcar_sound 2>; + }; + cpu@2 { + sound-dai = <&rcar_sound 3>; + }; + cpu@3 { + sound-dai = <&rcar_sound 4>; + }; + codec { + mclk-fs = <512>; + prefix = "pcm3168a"; + dai-tdm-slot-num = <8>; + sound-dai = <&pcm3168a 0>; + }; + }; + + simple-audio-card,dai-link@2 { + format = "i2s"; + bitclock-master = <&sndcpu2>; + frame-master = <&sndcpu2>; + + sndcpu2: cpu { + sound-dai = <&rcar_sound 5>; + }; + codec { + mclk-fs = <512>; + prefix = "pcm3168a"; + sound-dai = <&pcm3168a 1>; + }; + }; + }; From 8382f2949a0def8e9519603b77b3c26f81a66576 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 27 Apr 2020 09:29:53 -0700 Subject: [PATCH 155/428] ASoC: Intel: broadwell: Fix oops during module removal When removing the SOF module, the RT286 jack detect handler will oops if jack detection is not disabled. Disable the jack in the machine driver remove callback to prevent this. This fix is only for SOF support and is not needed for earlier versions. Signed-off-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200427162953.21107-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/broadwell.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index f9a8336a0541..86deea6f136a 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -230,7 +230,8 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { }, }; -static int broadwell_suspend(struct snd_soc_card *card){ +static int broadwell_disable_jack(struct snd_soc_card *card) +{ struct snd_soc_component *component; for_each_card_components(card, component) { @@ -241,9 +242,15 @@ static int broadwell_suspend(struct snd_soc_card *card){ break; } } + return 0; } +static int broadwell_suspend(struct snd_soc_card *card) +{ + return broadwell_disable_jack(card); +} + static int broadwell_resume(struct snd_soc_card *card){ struct snd_soc_component *component; @@ -292,8 +299,16 @@ static int broadwell_audio_probe(struct platform_device *pdev) return devm_snd_soc_register_card(&pdev->dev, &broadwell_rt286); } +static int broadwell_audio_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + return broadwell_disable_jack(card); +} + static struct platform_driver broadwell_audio = { .probe = broadwell_audio_probe, + .remove = broadwell_audio_remove, .driver = { .name = "broadwell-audio", }, From 726e6142b5c99b407a8118330598f82ba63617c3 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 27 Apr 2020 10:29:36 -0700 Subject: [PATCH 156/428] ASoC: SOF: topology: send ipc for all found DAIs in sof_set_dai_config We may find more than one DAIs in sof_set_dai_config() and we should send message to DSP for each DAI we found. Signed-off-by: Bard Liao Signed-off-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200427172939.25848-2-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 81 +++++++++------------------------------- 1 file changed, 18 insertions(+), 63 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index e88ffc25025f..0b15b4055f32 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2673,7 +2673,11 @@ static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config, } } -/* set config for all DAI's with name matching the link name */ +/* + * Send IPC and set the same config for all DAIs with name matching the link + * name. Note that the function can only be used for the case that all DAIs + * have a common DAI config for now. + */ static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, struct snd_soc_dai_link *link, struct sof_ipc_dai_config *config) @@ -2686,6 +2690,19 @@ static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, continue; if (strcmp(link->name, dai->name) == 0) { + struct sof_ipc_reply reply; + int ret; + + /* send message to DSP */ + ret = sof_ipc_tx_message(sdev->ipc, + config->hdr.cmd, config, size, + &reply, sizeof(reply)); + + if (ret < 0) { + dev_err(sdev->dev, "error: failed to set DAI config for %s index %d\n", + dai->name, config->dai_index); + return ret; + } dai->dai_config = kmemdup(config, size, GFP_KERNEL); if (!dai->dai_config) return -ENOMEM; @@ -2718,7 +2735,6 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; - struct sof_ipc_reply reply; u32 size = sizeof(*config); int ret; @@ -2767,17 +2783,6 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, return -EINVAL; } - /* send message to DSP */ - ret = sof_ipc_tx_message(sdev->ipc, - config->hdr.cmd, config, size, &reply, - sizeof(reply)); - - if (ret < 0) { - dev_err(scomp->dev, "error: failed to set DAI config for SSP%d\n", - config->dai_index); - return ret; - } - /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) @@ -2795,7 +2800,6 @@ static int sof_link_sai_load(struct snd_soc_component *scomp, int index, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; - struct sof_ipc_reply reply; u32 size = sizeof(*config); int ret; @@ -2835,17 +2839,6 @@ static int sof_link_sai_load(struct snd_soc_component *scomp, int index, return -EINVAL; } - /* send message to DSP */ - ret = sof_ipc_tx_message(sdev->ipc, - config->hdr.cmd, config, size, &reply, - sizeof(reply)); - - if (ret < 0) { - dev_err(scomp->dev, "error: failed to set DAI config for SAI%d\n", - config->dai_index); - return ret; - } - /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) @@ -2863,7 +2856,6 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; - struct sof_ipc_reply reply; u32 size = sizeof(*config); int ret; @@ -2904,16 +2896,6 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, return -EINVAL; } - /* send message to DSP */ - ret = sof_ipc_tx_message(sdev->ipc, - config->hdr.cmd, config, size, &reply, - sizeof(reply)); - if (ret < 0) { - dev_err(scomp->dev, "error: failed to set DAI config for ESAI%d\n", - config->dai_index); - return ret; - } - /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) @@ -2931,7 +2913,6 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; - struct sof_ipc_reply reply; struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; size_t size = sizeof(*config); @@ -3007,17 +2988,6 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) config->dmic.fifo_bits_b = config->dmic.fifo_bits; - /* send message to DSP */ - ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, - &reply, sizeof(reply)); - - if (ret < 0) { - dev_err(scomp->dev, - "error: failed to set DAI config for DMIC%d\n", - config->dai_index); - goto err; - } - /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) @@ -3142,7 +3112,6 @@ static int sof_link_alh_load(struct snd_soc_component *scomp, int index, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; - struct sof_ipc_reply reply; u32 size = sizeof(*config); int ret; @@ -3158,20 +3127,6 @@ static int sof_link_alh_load(struct snd_soc_component *scomp, int index, /* init IPC */ config->hdr.size = size; - dev_dbg(scomp->dev, "ALH config rate %d channels %d\n", - config->alh.rate, config->alh.channels); - - /* send message to DSP */ - ret = sof_ipc_tx_message(sdev->ipc, - config->hdr.cmd, config, size, &reply, - sizeof(reply)); - - if (ret < 0) { - dev_err(scomp->dev, "error: failed to set DAI config for ALH %d\n", - config->dai_index); - return ret; - } - /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) From 744a3bb3b4b6c4073ae9381a02c9824b29dd1a05 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 27 Apr 2020 10:29:37 -0700 Subject: [PATCH 157/428] ASoC: topology: set component dai_index to ipc dai config dai_index The ipc dai config dai_index is from topology. However, the same dai config will be applied to all DAIs in the same dai link. We have to ensure that the ipc dai config's dai_index match to the component's dai_index. Signed-off-by: Bard Liao Signed-off-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200427172939.25848-3-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 0b15b4055f32..0ed3ab35e9f9 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2693,6 +2693,14 @@ static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, struct sof_ipc_reply reply; int ret; + /* + * the same dai config will be applied to all DAIs in + * the same dai link. We have to ensure that the ipc + * dai config's dai_index match to the component's + * dai_index. + */ + config->dai_index = dai->comp_dai.dai_index; + /* send message to DSP */ ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, From ac764249485189fa0f019e48aeed7175c7b5376b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 27 Apr 2020 10:29:38 -0700 Subject: [PATCH 158/428] ASoC: SOF: topology: replace sof_link_hda_process by sof_set_dai_config Now we send ipc in sof_set_dai_config(), too. Therefore, we can use sof_set_dai_config() in sof_link_hda_load() just like other link load functions do. Signed-off-by: Bard Liao Signed-off-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200427172939.25848-4-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 64 ++-------------------------------------- 1 file changed, 3 insertions(+), 61 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 0ed3ab35e9f9..6fd75fe9f699 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3008,66 +3008,6 @@ err: return ret; } -/* - * for hda link, playback and capture are supported by different dai - * in FW. Here get the dai_index, set dma channel of each dai - * and send config to FW. In FW, each dai sets config by dai_index - */ -static int sof_link_hda_process(struct snd_sof_dev *sdev, - struct snd_soc_dai_link *link, - struct sof_ipc_dai_config *config) -{ - struct sof_ipc_reply reply; - u32 size = sizeof(*config); - struct snd_sof_dai *sof_dai; - int found = 0; - int ret; - - list_for_each_entry(sof_dai, &sdev->dai_list, list) { - if (!sof_dai->name) - continue; - - if (strcmp(link->name, sof_dai->name) == 0) { - 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) - 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, - &reply, sizeof(reply)); - - if (ret < 0) { - dev_err(sdev->dev, "error: failed to set DAI config for direction:%d of HDA dai %d\n", - sof_dai->comp_dai.direction, - config->dai_index); - - return ret; - } - } - } - - /* - * machine driver may define a dai link with playback and capture - * dai enabled, but the dai link in topology would support both, one - * or none of them. Here print a warning message to notify user - */ - if (!found) { - dev_warn(sdev->dev, "warning: failed to find dai for dai link %s", - link->name); - } - - return 0; -} - static int sof_link_hda_load(struct snd_soc_component *scomp, int index, struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg, @@ -3104,7 +3044,9 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, return -EINVAL; } - ret = sof_link_hda_process(sdev, link, config); + config->hda.link_dma_ch = DMA_CHAN_INVALID; + + ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) dev_err(scomp->dev, "error: failed to process hda dai link %s", link->name); From fd045558295e5dab4ebe3176401bafa7090fa007 Mon Sep 17 00:00:00 2001 From: randerwang Date: Mon, 27 Apr 2020 10:29:39 -0700 Subject: [PATCH 159/428] ASoC: SOF: Intel: change trigger sequence to fix pop noise when stopping playback on sdw platforms Now the trigger sequence is set to SND_SOC_DPCM_TRIGGER_POST for SOF. This means FE will be stopped before BE, so BE will consume invalid data and this generates huge pop noise. This sequence is introduced for HDA DAI which requires SND_SOC_DPCM_TRIGGER_POST for some reasons. Now set default trigger sequence to SND_SOC_DPCM_TRIGGER_PRE for playback with all DAI and fix sequence only for HDA DAI. Fully tested on Comet Lake for a few cycles. Signed-off-by: randerwang Signed-off-by: Ranjani Sridharan Reviewed-by: Clarex Zhou Reviewed-by: Guennadi Liakhovetski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200427172939.25848-5-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 12 +++++++++++- sound/soc/sof/topology.c | 14 +++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 0885826adb6c..e9679fcba428 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -639,6 +639,7 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = snd_sof_find_dai(component, (char *)rtd->dai_link->name); + struct snd_soc_dpcm *dpcm; /* no topology exists for this BE, try a common configuration */ if (!dai) { @@ -702,7 +703,16 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, } break; case SOF_DAI_INTEL_HDA: - /* do nothing for HDA dai_link */ + /* + * HDaudio does not follow the default trigger + * sequence due to firmware implementation + */ + for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { + struct snd_soc_pcm_runtime *fe = dpcm->fe; + + fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = + SND_SOC_DPCM_TRIGGER_POST; + } break; case SOF_DAI_INTEL_ALH: /* do nothing for ALH dai_link */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 6fd75fe9f699..8ab0fc558054 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3111,9 +3111,17 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, if (!link->no_pcm) { link->nonatomic = true; - /* set trigger order */ - link->trigger[0] = SND_SOC_DPCM_TRIGGER_POST; - link->trigger[1] = SND_SOC_DPCM_TRIGGER_POST; + /* + * set default trigger order for all links. Exceptions to + * the rule will be handled in sof_pcm_dai_link_fixup() + * For playback, the sequence is the following: start FE, + * start BE, stop BE, stop FE; for Capture the sequence is + * inverted start BE, start FE, stop FE, stop BE + */ + link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = + SND_SOC_DPCM_TRIGGER_PRE; + link->trigger[SNDRV_PCM_STREAM_CAPTURE] = + SND_SOC_DPCM_TRIGGER_POST; /* nothing more to do for FE dai links */ return 0; From 38c2e325a66b1c4d694d2a15b5efa81e5ae38872 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 30 Apr 2020 16:22:26 +0800 Subject: [PATCH 160/428] ASoC: rt5682: simplify assertions Simplifies assertions for errors. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200430082231.151127-2-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index d36f560ad7a8..e542aab46619 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -3462,7 +3462,7 @@ int rt5682_io_init(struct device *dev, struct sdw_slave *slave) ret = regmap_multi_reg_write(rt5682->regmap, patch_list, ARRAY_SIZE(patch_list)); - if (ret != 0) + if (ret) dev_warn(dev, "Failed to apply regmap patch: %d\n", ret); regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); @@ -3536,8 +3536,7 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, rt5682 = devm_kzalloc(&i2c->dev, sizeof(struct rt5682_priv), GFP_KERNEL); - - if (rt5682 == NULL) + if (!rt5682) return -ENOMEM; i2c_set_clientdata(i2c, rt5682); @@ -3562,14 +3561,14 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5682->supplies), rt5682->supplies); - if (ret != 0) { + if (ret) { dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); return ret; } ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies); - if (ret != 0) { + if (ret) { dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); return ret; } @@ -3599,7 +3598,7 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, ret = regmap_multi_reg_write(rt5682->regmap, patch_list, ARRAY_SIZE(patch_list)); - if (ret != 0) + if (ret) dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); From 5b8e09091b6092296a209a940e192ed2cc891efe Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 30 Apr 2020 16:22:27 +0800 Subject: [PATCH 161/428] ASoC: rt5682: fix space issues Fixes blank lines and indent issues. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200430082231.151127-3-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 152 ++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 82 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index e542aab46619..7a38028f5e10 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -806,6 +806,7 @@ static void rt5682_reset(struct rt5682_priv *rt5682) if (!rt5682->is_sdw) regmap_write(rt5682->regmap, RT5682_I2C_MODE, 1); } + /** * rt5682_sel_asrc_clk_src - select ASRC clock source for a set of filters * @component: SoC audio component device. @@ -823,7 +824,6 @@ static void rt5682_reset(struct rt5682_priv *rt5682) int rt5682_sel_asrc_clk_src(struct snd_soc_component *component, unsigned int filter_mask, unsigned int clk_src) { - switch (clk_src) { case RT5682_CLK_SEL_SYS: case RT5682_CLK_SEL_I2S1_ASRC: @@ -918,7 +918,6 @@ static int rt5682_headset_detect(struct snd_soc_component *component, unsigned int val, count; if (jack_insert) { - snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, RT5682_PWR_VREF2 | RT5682_PWR_MB, RT5682_PWR_VREF2 | RT5682_PWR_MB); @@ -952,7 +951,6 @@ static int rt5682_headset_detect(struct snd_soc_component *component, default: rt5682->jack_type = SND_JACK_HEADPHONE; } - } else { rt5682_enable_push_button_irq(component, false); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, @@ -979,7 +977,7 @@ static irqreturn_t rt5682_irq(int irq, void *data) struct rt5682_priv *rt5682 = data; mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, msecs_to_jiffies(250)); + &rt5682->jack_detect_work, msecs_to_jiffies(250)); return IRQ_HANDLED; } @@ -995,16 +993,16 @@ static void rt5682_jd_check_handler(struct work_struct *work) rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, - SND_JACK_HEADSET | - SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3); + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); } else { schedule_delayed_work(&rt5682->jd_check_work, 500); } } static int rt5682_set_jack_detect(struct snd_soc_component *component, - struct snd_soc_jack *hs_jack, void *data) + struct snd_soc_jack *hs_jack, void *data) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); @@ -1013,9 +1011,9 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, if (!rt5682->is_sdw) { if (!hs_jack) { regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, - RT5682_JD1_EN_MASK, RT5682_JD1_DIS); + RT5682_JD1_EN_MASK, RT5682_JD1_DIS); regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, - RT5682_POW_JDH | RT5682_POW_JDL, 0); + RT5682_POW_JDH | RT5682_POW_JDL, 0); cancel_delayed_work_sync(&rt5682->jack_detect_work); return 0; } @@ -1058,15 +1056,15 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, 0x7f7f, (rt5682->pdata.btndet_delay << 8 | rt5682->pdata.btndet_delay)); mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, - msecs_to_jiffies(250)); + &rt5682->jack_detect_work, + msecs_to_jiffies(250)); break; case RT5682_JD_NULL: regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, RT5682_JD1_EN_MASK, RT5682_JD1_DIS); regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, - RT5682_POW_JDH | RT5682_POW_JDL, 0); + RT5682_POW_JDH | RT5682_POW_JDL, 0); break; default: @@ -1148,9 +1146,9 @@ static void rt5682_jack_detect_handler(struct work_struct *work) } snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, - SND_JACK_HEADSET | - SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3); + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); if (!rt5682->is_sdw) { if (rt5682->jack_type & (SND_JACK_BTN_0 | SND_JACK_BTN_1 | @@ -1184,15 +1182,13 @@ static const struct snd_kcontrol_new rt5682_snd_controls[] = { 3, 0, adc_bst_tlv), }; - static int rt5682_div_sel(struct rt5682_priv *rt5682, - int target, const int div[], int size) + int target, const int div[], int size) { int i; if (rt5682->sysclk < target) { - pr_err("sysclk rate %d is too low\n", - rt5682->sysclk); + pr_err("sysclk rate %d is too low\n", rt5682->sysclk); return 0; } @@ -1201,18 +1197,17 @@ static int rt5682_div_sel(struct rt5682_priv *rt5682, if (target * div[i] == rt5682->sysclk) return i; if (target * div[i + 1] > rt5682->sysclk) { - dev_dbg(rt5682->component->dev, "can't find div for sysclk %d\n", + dev_dbg(rt5682->component->dev, + "can't find div for sysclk %d\n", rt5682->sysclk); return i; } } if (target * div[i] < rt5682->sysclk) - pr_err("sysclk rate %d is too high\n", - rt5682->sysclk); + pr_err("sysclk rate %d is too high\n", rt5682->sysclk); return size - 1; - } /** @@ -1226,7 +1221,7 @@ static int rt5682_div_sel(struct rt5682_priv *rt5682, * It is better for clock to approximate 3MHz. */ static int set_dmic_clk(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); @@ -1246,7 +1241,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, } static int set_filter_clk(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); @@ -1290,7 +1285,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, } static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w, - struct snd_soc_dapm_widget *sink) + struct snd_soc_dapm_widget *sink) { unsigned int val; struct snd_soc_component *component = @@ -1305,7 +1300,7 @@ static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w, } static int is_sys_clk_from_pll2(struct snd_soc_dapm_widget *w, - struct snd_soc_dapm_widget *sink) + struct snd_soc_dapm_widget *sink) { unsigned int val; struct snd_soc_component *component = @@ -1320,7 +1315,7 @@ static int is_sys_clk_from_pll2(struct snd_soc_dapm_widget *w, } static int is_using_asrc(struct snd_soc_dapm_widget *w, - struct snd_soc_dapm_widget *sink) + struct snd_soc_dapm_widget *sink) { unsigned int reg, shift, val; struct snd_soc_component *component = @@ -1347,7 +1342,6 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, default: return 0; } - } /* Digital Mixer */ @@ -1501,13 +1495,13 @@ static const struct snd_kcontrol_new rt5682_alg_dac_r1_mux = /* Out Switch */ static const struct snd_kcontrol_new hpol_switch = SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5682_HP_CTRL_1, - RT5682_L_MUTE_SFT, 1, 1); + RT5682_L_MUTE_SFT, 1, 1); static const struct snd_kcontrol_new hpor_switch = SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5682_HP_CTRL_1, - RT5682_R_MUTE_SFT, 1, 1); + RT5682_R_MUTE_SFT, 1, 1); static int rt5682_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); @@ -1538,11 +1532,10 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w, } return 0; - } static int set_dmic_power(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); @@ -1566,7 +1559,7 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w, } static int rt5682_set_verf(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); @@ -1743,23 +1736,23 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { /* Digital Interface Select */ SND_SOC_DAPM_MUX("IF1 01 ADC Swap Mux", SND_SOC_NOPM, 0, 0, - &rt5682_if1_01_adc_swap_mux), + &rt5682_if1_01_adc_swap_mux), SND_SOC_DAPM_MUX("IF1 23 ADC Swap Mux", SND_SOC_NOPM, 0, 0, - &rt5682_if1_23_adc_swap_mux), + &rt5682_if1_23_adc_swap_mux), SND_SOC_DAPM_MUX("IF1 45 ADC Swap Mux", SND_SOC_NOPM, 0, 0, - &rt5682_if1_45_adc_swap_mux), + &rt5682_if1_45_adc_swap_mux), SND_SOC_DAPM_MUX("IF1 67 ADC Swap Mux", SND_SOC_NOPM, 0, 0, - &rt5682_if1_67_adc_swap_mux), + &rt5682_if1_67_adc_swap_mux), SND_SOC_DAPM_MUX("IF2 ADC Swap Mux", SND_SOC_NOPM, 0, 0, - &rt5682_if2_adc_swap_mux), + &rt5682_if2_adc_swap_mux), SND_SOC_DAPM_MUX("ADCDAT Mux", SND_SOC_NOPM, 0, 0, - &rt5682_adcdat_pin_ctrl), + &rt5682_adcdat_pin_ctrl), SND_SOC_DAPM_MUX("DAC L Mux", SND_SOC_NOPM, 0, 0, - &rt5682_dac_l_mux), + &rt5682_dac_l_mux), SND_SOC_DAPM_MUX("DAC R Mux", SND_SOC_NOPM, 0, 0, - &rt5682_dac_r_mux), + &rt5682_dac_r_mux), /* Audio Interface */ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, @@ -1831,7 +1824,6 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { /* Output Lines */ SND_SOC_DAPM_OUTPUT("HPOL"), SND_SOC_DAPM_OUTPUT("HPOR"), - }; static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { @@ -1997,7 +1989,7 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { }; static int rt5682_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, - unsigned int rx_mask, int slots, int slot_width) + unsigned int rx_mask, int slots, int slot_width) { struct snd_soc_component *component = dai->component; unsigned int cl, val = 0; @@ -2065,9 +2057,8 @@ static int rt5682_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, return 0; } - static int rt5682_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); @@ -2085,7 +2076,7 @@ static int rt5682_hw_params(struct snd_pcm_substream *substream, } dev_dbg(dai->dev, "lrck is %dHz and pre_div is %d for iis %d\n", - rt5682->lrck[dai->id], pre_div, dai->id); + rt5682->lrck[dai->id], pre_div, dai->id); switch (params_width(params)) { case 16: @@ -2469,7 +2460,7 @@ static int rt5682_set_bclk2_ratio(struct snd_soc_dai *dai, unsigned int ratio) } static int rt5682_set_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) + enum snd_soc_bias_level level) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); @@ -2667,7 +2658,7 @@ static unsigned long rt5682_bclk_recalc_rate(struct clk_hw *hw, unsigned int bclks_per_wclk; snd_soc_component_read(component, RT5682_TDM_TCON_CTRL, - &bclks_per_wclk); + &bclks_per_wclk); switch (bclks_per_wclk & RT5682_TDM_BCLK_MS1_MASK) { case RT5682_TDM_BCLK_MS1_256: @@ -2954,7 +2945,7 @@ struct sdw_stream_data { }; static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, - int direction) + int direction) { struct sdw_stream_data *stream; @@ -2997,8 +2988,8 @@ static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + stream = snd_soc_dai_get_dma_data(dai, substream); if (!stream) return -ENOMEM; @@ -3114,7 +3105,7 @@ static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, } static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) + struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); @@ -3308,7 +3299,6 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4); mutex_unlock(&rt5682->calibrate_mutex); - } #if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW) @@ -3363,7 +3353,7 @@ static const struct regmap_config rt5682_sdw_regmap = { }; int rt5682_sdw_init(struct device *dev, struct regmap *regmap, - struct sdw_slave *slave) + struct sdw_slave *slave) { struct rt5682_priv *rt5682; int ret; @@ -3461,23 +3451,23 @@ int rt5682_io_init(struct device *dev, struct sdw_slave *slave) } ret = regmap_multi_reg_write(rt5682->regmap, patch_list, - ARRAY_SIZE(patch_list)); + ARRAY_SIZE(patch_list)); if (ret) dev_warn(dev, "Failed to apply regmap patch: %d\n", ret); regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, - RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, - RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); + RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, + RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, - RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); + RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1, - RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); + RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1, - RT5682_PM_HP_MASK, RT5682_PM_HP_HV); + RT5682_PM_HP_MASK, RT5682_PM_HP_HV); /* Soundwire */ regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266); @@ -3499,9 +3489,9 @@ int rt5682_io_init(struct device *dev, struct sdw_slave *slave) regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1, RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN); regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, - RT5682_POW_IRQ | RT5682_POW_JDH | - RT5682_POW_ANA, RT5682_POW_IRQ | - RT5682_POW_JDH | RT5682_POW_ANA); + RT5682_POW_IRQ | RT5682_POW_JDH | + RT5682_POW_ANA, RT5682_POW_IRQ | + RT5682_POW_JDH | RT5682_POW_ANA); regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, RT5682_PWR_JDH, RT5682_PWR_JDH); regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, @@ -3510,7 +3500,7 @@ int rt5682_io_init(struct device *dev, struct sdw_slave *slave) reinit: mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, msecs_to_jiffies(250)); + &rt5682->jack_detect_work, msecs_to_jiffies(250)); /* Mark Slave initialization complete */ rt5682->hw_init = true; @@ -3527,7 +3517,7 @@ EXPORT_SYMBOL_GPL(rt5682_io_init); #endif static int rt5682_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt5682_priv *rt5682; @@ -3597,7 +3587,7 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, rt5682_calibrate(rt5682); ret = regmap_multi_reg_write(rt5682->regmap, patch_list, - ARRAY_SIZE(patch_list)); + ARRAY_SIZE(patch_list)); if (ret) dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); @@ -3643,27 +3633,26 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, } regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, - RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, - RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); + RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, + RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, - RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, - RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); + RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, + RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, - RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); + RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1, - RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); + RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1, - RT5682_PM_HP_MASK, RT5682_PM_HP_HV); + RT5682_PM_HP_MASK, RT5682_PM_HP_HV); regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, - RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2); + RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2); INIT_DELAYED_WORK(&rt5682->jack_detect_work, - rt5682_jack_detect_handler); + rt5682_jack_detect_handler); INIT_DELAYED_WORK(&rt5682->jd_check_work, - rt5682_jd_check_handler); - + rt5682_jd_check_handler); if (i2c->irq) { ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, @@ -3671,12 +3660,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, | IRQF_ONESHOT, "rt5682", rt5682); if (ret) dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); - } return devm_snd_soc_register_component(&i2c->dev, - &soc_component_dev_rt5682, - rt5682_dai, ARRAY_SIZE(rt5682_dai)); + &soc_component_dev_rt5682, + rt5682_dai, ARRAY_SIZE(rt5682_dai)); } static void rt5682_i2c_shutdown(struct i2c_client *client) From 70255cf6917828a2caf93f79f15a09bd71803e61 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 30 Apr 2020 16:22:28 +0800 Subject: [PATCH 162/428] ASoC: rt5682: remove empty default case Removes empty default case. Also adds a missing break statement. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200430082231.151127-4-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 7a38028f5e10..d38b2e8a7f43 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -950,6 +950,7 @@ static int rt5682_headset_detect(struct snd_soc_component *component, break; default: rt5682->jack_type = SND_JACK_HEADPHONE; + break; } } else { rt5682_enable_push_button_irq(component, false); @@ -1526,9 +1527,6 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0000); break; - - default: - return 0; } return 0; @@ -1550,9 +1548,6 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w, /*Add delay to avoid pop noise*/ msleep(delay); break; - - default: - return 0; } return 0; @@ -1576,9 +1571,6 @@ static int rt5682_set_verf(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, RT5682_PWR_FV2, 0); break; - - default: - break; } break; @@ -1596,14 +1588,8 @@ static int rt5682_set_verf(struct snd_soc_dapm_widget *w, RT5682_PWR_ANLG_1, RT5682_PWR_FV2, RT5682_PWR_FV2); break; - - default: - break; } break; - - default: - return 0; } return 0; @@ -2483,8 +2469,7 @@ static int rt5682_set_bias_level(struct snd_soc_component *component, regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, RT5682_PWR_BG, 0); break; - - default: + case SND_SOC_BIAS_ON: break; } From 9c1cb755b5b325c18551f7d08438ea6896130acd Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 30 Apr 2020 16:22:29 +0800 Subject: [PATCH 163/428] ASoC: rt5682: replace message printing from pr_() to dev_() Replaces message printing from pr_() to dev_(). Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200430082231.151127-5-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index d38b2e8a7f43..bfe542dcc7ba 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -857,7 +857,7 @@ static int rt5682_button_detect(struct snd_soc_component *component) val = snd_soc_component_read32(component, RT5682_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5682_4BTN_IL_CMD_1, val); - pr_debug("%s btn_type=%x\n", __func__, btn_type); + dev_dbg(component->dev, "%s btn_type=%x\n", __func__, btn_type); snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_2, 0x10, 0x10); @@ -1189,7 +1189,8 @@ static int rt5682_div_sel(struct rt5682_priv *rt5682, int i; if (rt5682->sysclk < target) { - pr_err("sysclk rate %d is too low\n", rt5682->sysclk); + dev_err(rt5682->component->dev, + "sysclk rate %d is too low\n", rt5682->sysclk); return 0; } @@ -1206,7 +1207,8 @@ static int rt5682_div_sel(struct rt5682_priv *rt5682, } if (target * div[i] < rt5682->sysclk) - pr_err("sysclk rate %d is too high\n", rt5682->sysclk); + dev_err(rt5682->component->dev, + "sysclk rate %d is too high\n", rt5682->sysclk); return size - 1; } @@ -3272,7 +3274,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) } if (count >= 60) - pr_err("HP Calibration Failure\n"); + dev_err(rt5682->component->dev, "HP Calibration Failure\n"); /* restore settings */ regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0x02af); @@ -3391,7 +3393,7 @@ int rt5682_io_init(struct device *dev, struct sdw_slave *slave) regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); if (val != DEVICE_ID) { - pr_err("Device with ID register %x is not rt5682\n", val); + dev_err(dev, "Device with ID register %x is not rt5682\n", val); return -ENODEV; } @@ -3562,7 +3564,8 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); if (val != DEVICE_ID) { - pr_err("Device with ID register %x is not rt5682\n", val); + dev_err(&i2c->dev, + "Device with ID register %x is not rt5682\n", val); return -ENODEV; } From 2317e84979fb80821c0d3ef909f1a2b68ace37f9 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 30 Apr 2020 16:22:30 +0800 Subject: [PATCH 164/428] ASoC: rt5682: remove duplicate rt5682_reset() calls Removes duplicate rt5682_reset() calls. rt5682_calibrate() calls rt5682_reset() anyway. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200430082231.151127-6-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index bfe542dcc7ba..19fb9f1d8f49 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -3416,8 +3416,6 @@ int rt5682_io_init(struct device *dev, struct sdw_slave *slave) pm_runtime_get_noresume(&slave->dev); - rt5682_reset(rt5682); - if (rt5682->first_hw_init) { regcache_cache_only(rt5682->regmap, false); regcache_cache_bypass(rt5682->regmap, true); @@ -3569,8 +3567,6 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, return -ENODEV; } - rt5682_reset(rt5682); - mutex_init(&rt5682->calibrate_mutex); rt5682_calibrate(rt5682); From 4642126b852f46d5d6a16bc60d50fbe4920c2710 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 30 Apr 2020 16:22:31 +0800 Subject: [PATCH 165/428] ASoC: rt5682: remove unwanted btn_type assignment The following dev_err() is intended to print unexpected btn_type. Removes the unwanted btn_type assignment. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200430082231.151127-7-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 19fb9f1d8f49..5d3b11756a34 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -1134,7 +1134,6 @@ static void rt5682_jack_detect_handler(struct work_struct *work) case 0x0000: /* unpressed */ break; default: - btn_type = 0; dev_err(rt5682->component->dev, "Unexpected button code 0x%04x\n", btn_type); From f9dfa8f25462a2b9bb47dcb563688d616e21ee83 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 28 Apr 2020 23:27:36 +0200 Subject: [PATCH 166/428] ASoC: SOF: sort out Kconfig, again The imx8 config keeps causing issues: WARNING: unmet direct dependencies detected for SND_SOC_SOF_IMX8M Depends on [n]: SOUND [=y] && !UML && SND [=y] && SND_SOC [=m] && SND_SOC_SOF_TOPLEVEL [=y] && SND_SOC_SOF_IMX_TOPLEVEL [=y] && IMX_DSP [=n] Selected by [m]: - SND_SOC_SOF_IMX_OF [=m] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=m] && SND_SOC_SOF_TOPLEVEL [=y] && SND_SOC_SOF_IMX_TOPLEVEL [=y] && SND_SOC_SOF_IMX8M_SUPPORT [=y] This is complicated by two drivers having dependencies on both platform specific drivers and the SND_SOC_SOF_OF framework code, and using an somewhat obscure method to build them the same way as the SOC_SOF_OF symbol (built-in or modular). My solution now ensures that the two drivers can only be enabled when the dependencies are met: - When the platform specific drivers are built-in, everything is fine, as SOC_SOF_OF is either =y or =m - When both are loadable modules, it also works, both for Kconfig and at runtime - When the hardware drivers are loadable modules or disabled, and SOC_SOF_OF=y, prevent the IMX_SOF_OF drivers from being turned on, as this would be broken. It seems that this is just an elaborate way to describe two tristate symbols that have straight dependencies, but maybe I'm missing some subtle point. It seems to always build for me now. Fixes: fe57a92c8858 ("ASoC: SOF: Add missing dependency on IMX_SCU") Fixes: afb93d716533 ("ASoC: SOF: imx: Add i.MX8M HW support") Fixes: cb0312f61c3e ("ASoC: SOF: imx: fix undefined reference issue") Fixes: afb93d716533dd ("ASoC: SOF: imx: Add i.MX8M HW support") Signed-off-by: Arnd Bergmann Signed-off-by: Pierre-Louis Bossart Acked-by: Daniel Baluta Link: https://lore.kernel.org/r/20200428212752.2901778-1-arnd@arndb.de Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index f76660e91382..66684d7590f4 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -21,7 +21,8 @@ config SND_SOC_SOF_IMX_OF config SND_SOC_SOF_IMX8_SUPPORT bool "SOF support for i.MX8" - depends on IMX_SCU + depends on IMX_SCU=y || IMX_SCU=SND_SOC_SOF_IMX_OF + depends on IMX_DSP=y || IMX_DSP=SND_SOC_SOF_IMX_OF help This adds support for Sound Open Firmware for NXP i.MX8 platforms Say Y if you have such a device. @@ -29,14 +30,13 @@ config SND_SOC_SOF_IMX8_SUPPORT config SND_SOC_SOF_IMX8 tristate - depends on IMX_SCU - select IMX_DSP help This option is not user-selectable but automagically handled by 'select' statements at a higher level config SND_SOC_SOF_IMX8M_SUPPORT bool "SOF support for i.MX8M" + depends on IMX_DSP=y || IMX_DSP=SND_SOC_SOF_OF help This adds support for Sound Open Firmware for NXP i.MX8M platforms Say Y if you have such a device. @@ -44,7 +44,6 @@ config SND_SOC_SOF_IMX8M_SUPPORT config SND_SOC_SOF_IMX8M tristate - depends on IMX_DSP help This option is not user-selectable but automagically handled by 'select' statements at a higher level From dbd13179780555ecd3c992dea1222ca31920e892 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Thu, 30 Apr 2020 16:32:51 +0800 Subject: [PATCH 167/428] ALSA: hda/realtek - Introduce polarity for micmute LED GPIO Currently mute LED and micmute LED share the same GPIO polarity. So split the polarity for mute and micmute, in case they have different polarities. Signed-off-by: Kai-Heng Feng Link: https://lore.kernel.org/r/20200430083255.5093-1-kai.heng.feng@canonical.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c1a85c8f7b69..7e49c5ed5344 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -81,6 +81,7 @@ struct alc_spec { /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ int mute_led_polarity; + int micmute_led_polarity; hda_nid_t mute_led_nid; hda_nid_t cap_mute_led_nid; @@ -4075,11 +4076,9 @@ static void alc269_fixup_hp_mute_led_mic3(struct hda_codec *codec, /* update LED status via GPIO */ static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask, - bool enabled) + int polarity, bool enabled) { - struct alc_spec *spec = codec->spec; - - if (spec->mute_led_polarity) + if (polarity) enabled = !enabled; alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */ } @@ -4090,7 +4089,8 @@ static void alc_fixup_gpio_mute_hook(void *private_data, int enabled) struct hda_codec *codec = private_data; struct alc_spec *spec = codec->spec; - alc_update_gpio_led(codec, spec->gpio_mute_led_mask, enabled); + alc_update_gpio_led(codec, spec->gpio_mute_led_mask, + spec->mute_led_polarity, enabled); } /* turn on/off mic-mute LED via GPIO per capture hook */ @@ -4099,6 +4099,7 @@ static void alc_gpio_micmute_update(struct hda_codec *codec) struct alc_spec *spec = codec->spec; alc_update_gpio_led(codec, spec->gpio_mic_led_mask, + spec->micmute_led_polarity, spec->gen.micmute_led.led_value); } @@ -5795,7 +5796,8 @@ static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec, snd_hda_gen_hp_automute(codec, jack); /* mute_led_polarity is set to 0, so we pass inverted value here */ - alc_update_gpio_led(codec, 0x10, !spec->gen.hp_jack_present); + alc_update_gpio_led(codec, 0x10, spec->mute_led_polarity, + !spec->gen.hp_jack_present); } /* Manage GPIOs for HP EliteBook Folio 9480m. From 3e0650ab26e2010ee312311612e40e076ed1feca Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Thu, 30 Apr 2020 16:32:52 +0800 Subject: [PATCH 168/428] ALSA: hda/realtek - Enable micmute LED on and HP system Though the system uses DMIC, headset mic still uses the HDA, let's use GPIO 0x1 to control the micmute LED. The micmute LED GPIO has a different polarity to the mute LED GPIO, we can use the newly added micmute_led_polarity to indicate that. Signed-off-by: Kai-Heng Feng Link: https://lore.kernel.org/r/20200430083255.5093-2-kai.heng.feng@canonical.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7e49c5ed5344..dae403b14aa2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4134,7 +4134,11 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, static void alc285_fixup_hp_gpio_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - alc_fixup_hp_gpio_led(codec, action, 0x04, 0x00); + struct alc_spec *spec = codec->spec; + + spec->micmute_led_polarity = 1; + + alc_fixup_hp_gpio_led(codec, action, 0x04, 0x01); } static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, From 87dc36482cab3a4ea34f203fc3f4da35712eb783 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Thu, 30 Apr 2020 21:52:07 +0800 Subject: [PATCH 169/428] ALSA: hda/realtek - Add LED class support for micmute LED Currently DMIC controls micmute LED via "audio mute LED trigger". However, unlike Dell and Lenovo platforms, HP platforms don't provide a way to control micmute LED via ACPI, it's controlled by HDA codec instead. So let's register an LED class for micmute so other subsystems like DMIC can facilitate the codec-controlled LED. Signed-off-by: Kai-Heng Feng Link: https://lore.kernel.org/r/20200430135209.14703-1-kai.heng.feng@canonical.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index dae403b14aa2..b6a1c8b7f5d0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -4103,6 +4104,26 @@ static void alc_gpio_micmute_update(struct hda_codec *codec) spec->gen.micmute_led.led_value); } +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) +static int micmute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); + struct alc_spec *spec = codec->spec; + + alc_update_gpio_led(codec, spec->gpio_mic_led_mask, + spec->micmute_led_polarity, !!brightness); + return 0; +} + +static struct led_classdev micmute_led_cdev = { + .name = "hda::micmute", + .max_brightness = 1, + .brightness_set_blocking = micmute_led_set, + .default_trigger = "audio-micmute", +}; +#endif + /* setup mute and mic-mute GPIO bits, add hooks appropriately */ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, int action, @@ -4110,6 +4131,7 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, unsigned int micmute_mask) { struct alc_spec *spec = codec->spec; + int err; alc_fixup_gpio(codec, action, mute_mask | micmute_mask); @@ -4122,6 +4144,13 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, if (micmute_mask) { spec->gpio_mic_led_mask = micmute_mask; snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); + +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) + micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE); + err = devm_led_classdev_register(&codec->core.dev, &micmute_led_cdev); + if (err) + codec_warn(codec, "failed to register micmute LED\n"); +#endif } } From 0127f59794b39debf2daf3c7ff755236630198ed Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 1 May 2020 09:28:56 +0200 Subject: [PATCH 170/428] ALSA: hda/realtek - Fix unused variable warning w/o CONFIG_LEDS_TRIGGER_AUDIO Cover with a proper ifdef around the variable declaration for fixing the following compilation warning without CONFIG_LEDS_TRIGGER_AUDIO: sound/pci/hda/patch_realtek.c: In function 'alc_fixup_hp_gpio_led': sound/pci/hda/patch_realtek.c:4134:6: warning: unused variable 'err' [-Wunused-variable] Reported-by: Stephen Rothwell Fixes: 87dc36482cab ("ALSA: hda/realtek - Add LED class support for micmute LED") Link: https://lore.kernel.org/r/20200501072857.13720-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b6a1c8b7f5d0..670e59b081d5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4131,7 +4131,9 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, unsigned int micmute_mask) { struct alc_spec *spec = codec->spec; +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) int err; +#endif alc_fixup_gpio(codec, action, mute_mask | micmute_mask); From 7f0d5053c5a9d23fe5c2d337495a9d79038d267b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 May 2020 12:40:11 +0300 Subject: [PATCH 171/428] ALSA: isa/wavefront: prevent out of bounds write in ioctl The "header->number" comes from the ioctl and it needs to be clamped to prevent out of bounds writes. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20200501094011.GA960082@mwanda Signed-off-by: Takashi Iwai --- sound/isa/wavefront/wavefront_synth.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index c5b1d5900eed..d6420d224d09 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -1171,7 +1171,10 @@ wavefront_send_alias (snd_wavefront_t *dev, wavefront_patch_info *header) "alias for %d\n", header->number, header->hdr.a.OriginalSample); - + + if (header->number >= WF_MAX_SAMPLE) + return -EINVAL; + munge_int32 (header->number, &alias_hdr[0], 2); munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2); munge_int32 (*((unsigned int *)&header->hdr.a.sampleStartOffset), @@ -1202,6 +1205,9 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header) int num_samples; unsigned char *msample_hdr; + if (header->number >= WF_MAX_SAMPLE) + return -EINVAL; + msample_hdr = kmalloc(WF_MSAMPLE_BYTES, GFP_KERNEL); if (! msample_hdr) return -ENOMEM; From 49c22696348d6e7c8a2ecfd7e60fddfe188ded82 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Thu, 30 Apr 2020 17:11:39 +0800 Subject: [PATCH 172/428] ASoC: SOF: Update correct LED status at the first time usage of update_mute_led() At the first time update_mute_led() gets called, if channels are already muted, the temp value equals to led_value as 0, skipping the following LED setting. So set led_value to -1 as an uninitialized state, to update the correct LED status at first time usage. Fixes: 5d43001ae436 ("ASoC: SOF: acpi led support for switch controls") Signed-off-by: Kai-Heng Feng Reviewed-by: Ranjani Sridharan Acked-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200430091139.7003-1-kai.heng.feng@canonical.com Signed-off-by: Mark Brown --- sound/soc/sof/control.c | 4 ++-- sound/soc/sof/sof-audio.h | 2 +- sound/soc/sof/topology.c | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index dfc412e2d956..6d63768d42aa 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -19,8 +19,8 @@ static void update_mute_led(struct snd_sof_control *scontrol, struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - unsigned int temp = 0; - unsigned int mask; + int temp = 0; + int mask; int i; mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index bf65f31af858..875a5fc13297 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -56,7 +56,7 @@ struct snd_sof_pcm { struct snd_sof_led_control { unsigned int use_led; unsigned int direction; - unsigned int led_value; + int led_value; }; /* ALSA SOF Kcontrol device */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index fe8ba3e05e08..ab2b69de1d4d 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1203,6 +1203,8 @@ static int sof_control_load(struct snd_soc_component *scomp, int index, return ret; } + scontrol->led_ctl.led_value = -1; + dobj->private = scontrol; list_add(&scontrol->list, &sdev->kcontrol_list); return ret; From f139546fb7d436145cbbffa346de7d5353c84fdf Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 1 May 2020 10:16:25 -0500 Subject: [PATCH 173/428] ASoC: Intel: boards: sof-wm8804: support for Hifiberry Digiplus boards Add a new machine driver to interface with WM8804. The code is based on settings found in sound/soc/bcm/hifiberry-digi.c in the Raspberry PI tree. Tested on Up2 with Digi+ IO (capture+playback) and Digi+ PRO (playback with two local oscillators supported). The codec is clock master in both cases. Capture support has known clocking restrictions: the transmitter needs to be active for the clock recovery, the "Tx Source" mixer set to "S/PDIF RX". Playback will only work while capture is active. When Capture is not desired, or when there is no RX connector, the "Tx Source" mixer should be set to "AIF" Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200501151625.17820-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 15 ++ sound/soc/intel/boards/Makefile | 2 + sound/soc/intel/boards/sof_wm8804.c | 298 ++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+) create mode 100644 sound/soc/intel/boards/sof_wm8804.c diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 3ee7c006a860..91ce347b3a45 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -324,6 +324,21 @@ config SND_SOC_INTEL_BXT_RT298_MACH endif ## SND_SOC_INTEL_APL +if SND_SOC_SOF_APOLLOLAKE + +config SND_SOC_INTEL_SOF_WM8804_MACH + tristate "SOF with Wolfson/Cirrus WM8804 codec" + depends on I2C && ACPI + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_WM8804_I2C + help + This adds support for ASoC machine driver for Intel platforms + with the Wolfson/Cirrus WM8804 I2S audio codec. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + +endif ## SND_SOC_SOF_APOLLOLAKE + if SND_SOC_INTEL_KBL config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 98bf42463a1b..ddee0ea4032c 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -8,6 +8,7 @@ snd-soc-sst-broadwell-objs := broadwell.o snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o hda_dsp_common.o snd-soc-sst-bxt-rt298-objs := bxt_rt298.o hda_dsp_common.o snd-soc-sst-sof-pcm512x-objs := sof_pcm512x.o hda_dsp_common.o +snd-soc-sst-sof-wm8804-objs := sof_wm8804.o snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o obj-$(CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH) += snd-soc-sst-sof-pcm512x.o +obj-$(CONFIG_SND_SOC_INTEL_SOF_WM8804_MACH) += snd-soc-sst-sof-wm8804.o obj-$(CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH) += snd-soc-sst-glk-rt5682_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c new file mode 100644 index 000000000000..c13fd20da559 --- /dev/null +++ b/sound/soc/intel/boards/sof_wm8804.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2018-2020, Intel Corporation +// +// sof-wm8804.c - ASoC machine driver for Up and Up2 board +// based on WM8804/Hifiberry Digi+ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../codecs/wm8804.h" + +struct sof_card_private { + struct gpio_desc *gpio_44; + struct gpio_desc *gpio_48; + int sample_rate; +}; + +#define SOF_WM8804_UP2_QUIRK BIT(0) + +static unsigned long sof_wm8804_quirk; + +static int sof_wm8804_quirk_cb(const struct dmi_system_id *id) +{ + sof_wm8804_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id sof_wm8804_quirk_table[] = { + { + .callback = sof_wm8804_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_MATCH(DMI_PRODUCT_NAME, "UP-APL01"), + }, + .driver_data = (void *)SOF_WM8804_UP2_QUIRK, + }, + {} +}; + +static int sof_wm8804_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 = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *codec = codec_dai->component; + const int sysclk = 27000000; /* This is fixed on this board */ + int samplerate; + long mclk_freq; + int mclk_div; + int sampling_freq; + bool clk_44; + int ret; + + samplerate = params_rate(params); + if (samplerate == ctx->sample_rate) + return 0; + + ctx->sample_rate = 0; + + if (samplerate <= 96000) { + mclk_freq = samplerate * 256; + mclk_div = WM8804_MCLKDIV_256FS; + } else { + mclk_freq = samplerate * 128; + mclk_div = WM8804_MCLKDIV_128FS; + } + + switch (samplerate) { + case 32000: + sampling_freq = 0x03; + break; + case 44100: + sampling_freq = 0x00; + break; + case 48000: + sampling_freq = 0x02; + break; + case 88200: + sampling_freq = 0x08; + break; + case 96000: + sampling_freq = 0x0a; + break; + case 176400: + sampling_freq = 0x0c; + break; + case 192000: + sampling_freq = 0x0e; + break; + default: + dev_err(rtd->card->dev, + "unsupported samplerate %d\n", samplerate); + return -EINVAL; + } + + if (samplerate % 16000) + clk_44 = true; /* use 44.1 kHz root frequency */ + else + clk_44 = false; + + if (!(IS_ERR_OR_NULL(ctx->gpio_44) || + IS_ERR_OR_NULL(ctx->gpio_48))) { + /* + * ensure both GPIOs are LOW first, then drive the + * relevant one to HIGH + */ + if (clk_44) { + gpiod_set_value_cansleep(ctx->gpio_48, !clk_44); + gpiod_set_value_cansleep(ctx->gpio_44, clk_44); + } else { + gpiod_set_value_cansleep(ctx->gpio_44, clk_44); + gpiod_set_value_cansleep(ctx->gpio_48, !clk_44); + } + } + + snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); + snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); + + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, + sysclk, SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(rtd->card->dev, + "Failed to set WM8804 SYSCLK: %d\n", ret); + return ret; + } + + /* set sampling frequency status bits */ + snd_soc_component_update_bits(codec, WM8804_SPDTX4, 0x0f, + sampling_freq); + + ctx->sample_rate = samplerate; + + return 0; +} + +/* machine stream operations */ +static struct snd_soc_ops sof_wm8804_ops = { + .hw_params = sof_wm8804_hw_params, +}; + +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-1AEC8804:00", "wm8804-spdif"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0"))); + +static struct snd_soc_dai_link dailink[] = { + /* back ends */ + { + .name = "SSP5-Codec", + .id = 0, + .no_pcm = 1, + .nonatomic = true, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ops = &sof_wm8804_ops, + SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), + }, +}; + +/* SoC card */ +static struct snd_soc_card sof_wm8804_card = { + .name = "wm8804", /* sof- prefix added automatically */ + .owner = THIS_MODULE, + .dai_link = dailink, + .num_links = ARRAY_SIZE(dailink), +}; + + /* i2c-:00 with HID being 8 chars */ +static char codec_name[SND_ACPI_I2C_ID_LEN]; + +/* + * to control the HifiBerry Digi+ PRO, it's required to toggle GPIO to + * select the clock source. On the Up2 board, this means + * Pin29/BCM5/Linux GPIO 430 and Pin 31/BCM6/ Linux GPIO 404. + * + * Using the ACPI device name is not very nice, but since we only use + * the value for the Up2 board there is no risk of conflict with other + * platforms. + */ + +static struct gpiod_lookup_table up2_gpios_table = { + /* .dev_id is set during probe */ + .table = { + GPIO_LOOKUP("INT3452:01", 73, "BCM-GPIO5", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("INT3452:01", 74, "BCM-GPIO6", GPIO_ACTIVE_HIGH), + { }, + }, +}; + +static int sof_wm8804_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card; + struct snd_soc_acpi_mach *mach; + struct sof_card_private *ctx; + struct acpi_device *adev; + int dai_index = 0; + int ret; + int i; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + mach = pdev->dev.platform_data; + card = &sof_wm8804_card; + card->dev = &pdev->dev; + + dmi_check_system(sof_wm8804_quirk_table); + + if (sof_wm8804_quirk & SOF_WM8804_UP2_QUIRK) { + up2_gpios_table.dev_id = dev_name(&pdev->dev); + gpiod_add_lookup_table(&up2_gpios_table); + + /* + * The gpios are required for specific boards with + * local oscillators, and optional in other cases. + * Since we can't identify when they are needed, use + * the GPIO as non-optional + */ + + ctx->gpio_44 = devm_gpiod_get(&pdev->dev, "BCM-GPIO5", + GPIOD_OUT_LOW); + if (IS_ERR(ctx->gpio_44)) { + ret = PTR_ERR(ctx->gpio_44); + dev_err(&pdev->dev, + "could not get BCM-GPIO5: %d\n", + ret); + return ret; + } + + ctx->gpio_48 = devm_gpiod_get(&pdev->dev, "BCM-GPIO6", + GPIOD_OUT_LOW); + if (IS_ERR(ctx->gpio_48)) { + ret = PTR_ERR(ctx->gpio_48); + dev_err(&pdev->dev, + "could not get BCM-GPIO6: %d\n", + ret); + return ret; + } + } + + /* fix index of codec dai */ + for (i = 0; i < ARRAY_SIZE(dailink); i++) { + if (!strcmp(dailink[i].codecs->name, "i2c-1AEC8804: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), + "%s%s", "i2c-", acpi_dev_name(adev)); + put_device(&adev->dev); + dailink[dai_index].codecs->name = codec_name; + } + + snd_soc_card_set_drvdata(card, ctx); + + return devm_snd_soc_register_card(&pdev->dev, card); +} + +static int sof_wm8804_remove(struct platform_device *pdev) +{ + if (sof_wm8804_quirk & SOF_WM8804_UP2_QUIRK) + gpiod_remove_lookup_table(&up2_gpios_table); + return 0; +} + +static struct platform_driver sof_wm8804_driver = { + .driver = { + .name = "sof-wm8804", + .pm = &snd_soc_pm_ops, + }, + .probe = sof_wm8804_probe, + .remove = sof_wm8804_remove, +}; +module_platform_driver(sof_wm8804_driver); + +MODULE_DESCRIPTION("ASoC Intel(R) SOF + WM8804 Machine driver"); +MODULE_AUTHOR("Pierre-Louis Bossart"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sof-wm8804"); From 8c149b7d75e53be47648742f40fc90d9fc6fa63a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 1 May 2020 15:35:34 +0200 Subject: [PATCH 174/428] dt-bindings: sound: wm8994: Correct required supplies based on actual implementaion The required supplies in bindings were actually not matching implementation making the bindings incorrect and misleading. The Linux kernel driver requires all supplies to be present. Also for wlf,wm8994 uses just DBVDD-supply instead of DBVDDn-supply (n: <1,3>). Reported-by: Jonathan Bakker Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200501133534.6706-1-krzk@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wm8994.txt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/wm8994.txt b/Documentation/devicetree/bindings/sound/wm8994.txt index 68cccc4653ba..367b58ce1bb9 100644 --- a/Documentation/devicetree/bindings/sound/wm8994.txt +++ b/Documentation/devicetree/bindings/sound/wm8994.txt @@ -14,9 +14,15 @@ Required properties: - #gpio-cells : Must be 2. The first cell is the pin number and the second cell is used to specify optional parameters (currently unused). - - AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply, - SPKVDD1-supply, SPKVDD2-supply : power supplies for the device, as covered - in Documentation/devicetree/bindings/regulator/regulator.txt + - power supplies for the device, as covered in + Documentation/devicetree/bindings/regulator/regulator.txt, depending + on compatible: + - for wlf,wm1811 and wlf,wm8958: + AVDD1-supply, AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, + DCVDD-supply, CPVDD-supply, SPKVDD1-supply, SPKVDD2-supply + - for wlf,wm8994: + AVDD1-supply, AVDD2-supply, DBVDD-supply, DCVDD-supply, CPVDD-supply, + SPKVDD1-supply, SPKVDD2-supply Optional properties: @@ -73,11 +79,11 @@ wm8994: codec@1a { lineout1-se; + AVDD1-supply = <®ulator>; AVDD2-supply = <®ulator>; CPVDD-supply = <®ulator>; - DBVDD1-supply = <®ulator>; - DBVDD2-supply = <®ulator>; - DBVDD3-supply = <®ulator>; + DBVDD-supply = <®ulator>; + DCVDD-supply = <®ulator>; SPKVDD1-supply = <®ulator>; SPKVDD2-supply = <®ulator>; }; From e149ca29f3994ca79e9e77aa2f5b2e871e9f7c99 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 1 May 2020 09:58:50 -0500 Subject: [PATCH 175/428] ASoC: SOF/Intel: clarify SPDX license with GPL-2.0-only Remove the ambiguity with GPL-2.0 and use an explicit GPL-2.0-only tag. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200501145850.15178-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-acpi.h | 2 +- include/sound/sof.h | 2 +- include/sound/sof/channel_map.h | 2 +- include/sound/sof/control.h | 2 +- include/sound/sof/dai-imx.h | 2 +- include/sound/sof/dai-intel.h | 2 +- include/sound/sof/dai.h | 2 +- include/sound/sof/header.h | 2 +- include/sound/sof/info.h | 2 +- include/sound/sof/pm.h | 2 +- include/sound/sof/stream.h | 2 +- include/sound/sof/topology.h | 2 +- include/sound/sof/trace.h | 2 +- include/sound/sof/xtensa.h | 2 +- sound/hda/intel-nhlt.c | 2 +- sound/soc/intel/Makefile | 2 +- sound/soc/intel/atom/Makefile | 2 +- sound/soc/intel/atom/sst/Makefile | 2 +- sound/soc/intel/boards/Makefile | 2 +- sound/soc/intel/boards/bytcht_cx2072x.c | 2 +- sound/soc/intel/boards/cml_rt1011_rt5682.c | 2 +- sound/soc/intel/boards/ehl_rt5660.c | 2 +- sound/soc/intel/boards/glk_rt5682_max98357a.c | 2 +- sound/soc/intel/boards/hda_dsp_common.c | 2 +- sound/soc/intel/boards/hda_dsp_common.h | 2 +- sound/soc/intel/boards/kbl_da7219_max98357a.c | 2 +- sound/soc/intel/boards/kbl_da7219_max98927.c | 2 +- sound/soc/intel/boards/kbl_rt5660.c | 2 +- sound/soc/intel/boards/skl_hda_dsp_common.c | 2 +- sound/soc/intel/boards/skl_hda_dsp_common.h | 2 +- sound/soc/intel/boards/skl_hda_dsp_generic.c | 2 +- sound/soc/intel/boards/sof_da7219_max98373.c | 2 +- sound/soc/intel/boards/sof_maxim_common.c | 2 +- sound/soc/intel/boards/sof_maxim_common.h | 2 +- sound/soc/intel/boards/sof_pcm512x.c | 2 +- sound/soc/intel/boards/sof_rt5682.c | 2 +- sound/soc/intel/boards/sof_sdw.c | 2 +- sound/soc/intel/boards/sof_sdw_common.h | 2 +- sound/soc/intel/boards/sof_sdw_dmic.c | 2 +- sound/soc/intel/boards/sof_sdw_hdmi.c | 2 +- sound/soc/intel/boards/sof_sdw_rt1308.c | 2 +- sound/soc/intel/boards/sof_sdw_rt5682.c | 2 +- sound/soc/intel/boards/sof_sdw_rt700.c | 2 +- sound/soc/intel/boards/sof_sdw_rt711.c | 2 +- sound/soc/intel/boards/sof_sdw_rt715.c | 2 +- sound/soc/intel/common/Makefile | 2 +- sound/soc/intel/common/soc-acpi-intel-bxt-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-cfl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-cml-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-cnl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-ehl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-glk-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-hda-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-icl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-jsl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-kbl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-skl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 2 +- sound/soc/intel/common/soc-intel-quirks.h | 2 +- sound/soc/intel/skylake/Makefile | 2 +- sound/soc/intel/skylake/skl-ssp-clk.c | 2 +- sound/soc/sof/Makefile | 2 +- sound/soc/sof/compress.c | 2 +- sound/soc/sof/compress.h | 2 +- sound/soc/sof/control.c | 2 +- sound/soc/sof/core.c | 2 +- sound/soc/sof/debug.c | 2 +- sound/soc/sof/imx/Kconfig | 2 +- sound/soc/sof/imx/Makefile | 2 +- sound/soc/sof/imx/imx8.c | 2 +- sound/soc/sof/imx/imx8m.c | 2 +- sound/soc/sof/intel/Makefile | 2 +- sound/soc/sof/intel/apl.c | 2 +- sound/soc/sof/intel/bdw.c | 2 +- sound/soc/sof/intel/byt.c | 2 +- sound/soc/sof/intel/cnl.c | 2 +- sound/soc/sof/intel/hda-bus.c | 2 +- sound/soc/sof/intel/hda-codec.c | 2 +- sound/soc/sof/intel/hda-compress.c | 2 +- sound/soc/sof/intel/hda-ctrl.c | 2 +- sound/soc/sof/intel/hda-dai.c | 2 +- sound/soc/sof/intel/hda-dsp.c | 2 +- sound/soc/sof/intel/hda-ipc.c | 2 +- sound/soc/sof/intel/hda-ipc.h | 2 +- sound/soc/sof/intel/hda-loader.c | 2 +- sound/soc/sof/intel/hda-pcm.c | 2 +- sound/soc/sof/intel/hda-stream.c | 2 +- sound/soc/sof/intel/hda-trace.c | 2 +- sound/soc/sof/intel/hda.c | 2 +- sound/soc/sof/intel/hda.h | 2 +- sound/soc/sof/intel/intel-ipc.c | 2 +- sound/soc/sof/intel/shim.h | 2 +- sound/soc/sof/ipc.c | 2 +- sound/soc/sof/loader.c | 2 +- sound/soc/sof/nocodec.c | 2 +- sound/soc/sof/ops.c | 2 +- sound/soc/sof/ops.h | 2 +- sound/soc/sof/pcm.c | 2 +- sound/soc/sof/pm.c | 2 +- sound/soc/sof/probe.c | 2 +- sound/soc/sof/probe.h | 2 +- sound/soc/sof/sof-acpi-dev.c | 2 +- sound/soc/sof/sof-audio.c | 2 +- sound/soc/sof/sof-audio.h | 2 +- sound/soc/sof/sof-of-dev.c | 2 +- sound/soc/sof/sof-pci-dev.c | 2 +- sound/soc/sof/sof-priv.h | 2 +- sound/soc/sof/topology.c | 2 +- sound/soc/sof/trace.c | 2 +- sound/soc/sof/utils.c | 2 +- sound/soc/sof/xtensa/Makefile | 2 +- sound/soc/sof/xtensa/core.c | 2 +- 112 files changed, 112 insertions(+), 112 deletions(-) diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index 392e953d561e..d2e9e3b4d7ea 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only * * Copyright (C) 2013-15, Intel Corporation. All rights reserved. */ diff --git a/include/sound/sof.h b/include/sound/sof.h index 969f554b0b7d..f3e716c8ce1c 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/channel_map.h b/include/sound/sof/channel_map.h index 21044eb5f377..fd3a30fcf756 100644 --- a/include/sound/sof/channel_map.h +++ b/include/sound/sof/channel_map.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/control.h b/include/sound/sof/control.h index 6080ea0facd7..7379a33d7247 100644 --- a/include/sound/sof/control.h +++ b/include/sound/sof/control.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/dai-imx.h b/include/sound/sof/dai-imx.h index ff9088dcc6f2..ca8325353d41 100644 --- a/include/sound/sof/dai-imx.h +++ b/include/sound/sof/dai-imx.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * Copyright 2019 NXP * diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 896db2243d87..136adf6686e2 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h index 2565edd336f1..34f135adf8ec 100644 --- a/include/sound/sof/dai.h +++ b/include/sound/sof/dai.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index b79479575cc8..2d35997ace40 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index d5eff3179a39..5a55ba8b7e56 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/pm.h b/include/sound/sof/pm.h index 3cf2e0f39d94..366aa6ec442b 100644 --- a/include/sound/sof/pm.h +++ b/include/sound/sof/pm.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/stream.h b/include/sound/sof/stream.h index 7facefb541b3..58a0d49977d6 100644 --- a/include/sound/sof/stream.h +++ b/include/sound/sof/stream.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 08267d284edc..872de52b3144 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h index 8056f214946d..c31a94a13ce0 100644 --- a/include/sound/sof/trace.h +++ b/include/sound/sof/trace.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/include/sound/sof/xtensa.h b/include/sound/sof/xtensa.h index dd53d36b34e1..87a07e520415 100644 --- a/include/sound/sof/xtensa.h +++ b/include/sound/sof/xtensa.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c index 99a23fe7fab9..73d4f8c4f4c7 100644 --- a/sound/hda/intel-nhlt.c +++ b/sound/hda/intel-nhlt.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2015-2019 Intel Corporation #include diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 8160520fd74c..e16d6dc4d4e6 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only # Core support obj-$(CONFIG_SND_SOC) += common/ diff --git a/sound/soc/intel/atom/Makefile b/sound/soc/intel/atom/Makefile index 1dc60471b399..a9326d5ec44c 100644 --- a/sound/soc/intel/atom/Makefile +++ b/sound/soc/intel/atom/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-soc-sst-atom-hifi2-platform-objs := sst-mfld-platform-pcm.o \ sst-mfld-platform-compress.o \ sst-atom-controls.o diff --git a/sound/soc/intel/atom/sst/Makefile b/sound/soc/intel/atom/sst/Makefile index 795d1cf8f386..f17c905df3e2 100644 --- a/sound/soc/intel/atom/sst/Makefile +++ b/sound/soc/intel/atom/sst/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-intel-sst-core-objs := sst.o sst_ipc.o sst_stream.o sst_drv_interface.o sst_loader.o sst_pvt.o snd-intel-sst-pci-objs += sst_pci.o snd-intel-sst-acpi-objs += sst_acpi.o diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index ddee0ea4032c..15684610f8c6 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-soc-sst-haswell-objs := haswell.o snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 3b3df7c9008c..c7f81a93d7c8 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // ASoC DPCM Machine driver for Baytrail / Cherrytrail platforms with // CX2072X codec diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index da6fefaf6785..68eff29daf8f 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2019 Intel Corporation. /* diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c index 2e3244d5496b..78160e3b1615 100644 --- a/sound/soc/intel/boards/ehl_rt5660.c +++ b/sound/soc/intel/boards/ehl_rt5660.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index f13158e4a1fc..48eda1a8aa6c 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2018 Intel Corporation. /* diff --git a/sound/soc/intel/boards/hda_dsp_common.c b/sound/soc/intel/boards/hda_dsp_common.c index 9179f07f9ee4..244b57fba64c 100644 --- a/sound/soc/intel/boards/hda_dsp_common.c +++ b/sound/soc/intel/boards/hda_dsp_common.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // Copyright(c) 2019 Intel Corporation. All rights reserved. diff --git a/sound/soc/intel/boards/hda_dsp_common.h b/sound/soc/intel/boards/hda_dsp_common.h index 431f7f09dccb..727edd256962 100644 --- a/sound/soc/intel/boards/hda_dsp_common.h +++ b/sound/soc/intel/boards/hda_dsp_common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright(c) 2019 Intel Corporation. */ diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index 32cd90b8d4c4..dc3d897ad280 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2017-18 Intel Corporation. /* diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index abd4e3839678..cc9b5eab8b4a 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2018 Intel Corporation. /* diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c index 6460e3f0c974..d2a078454784 100644 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ b/sound/soc/intel/boards/kbl_rt5660.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2018-19 Canonical Corporation. /* diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c index 78ff5f24c40e..07bfb2e64b3b 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.c +++ b/sound/soc/intel/boards/skl_hda_dsp_common.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2015-18 Intel Corporation. /* diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h index e8545d13062f..507750ef67f3 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.h +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright(c) 2015-18 Intel Corporation. */ diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index fc9290fb4e99..79c8947f840b 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2015-18 Intel Corporation. /* diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index 8ca8f76470fa..703703858595 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2019 Intel Corporation. /* diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index 463b39a7ccfd..1a549b32d1c9 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // Copyright(c) 2020 Intel Corporation. All rights reserved. #include diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index 406bf0e81155..785b34335368 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright(c) 2020 Intel Corporation. */ diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index fb7811899999..f983c7fbb1d1 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2018-2020 Intel Corporation. /* diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 8c29431b5847..13a48b0c35ae 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2019-2020 Intel Corporation. /* diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index cffc790fc2ea..bbbc802624f8 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index dd593ff3575b..69b363b8a686 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only * Copyright (c) 2020 Intel Corporation */ diff --git a/sound/soc/intel/boards/sof_sdw_dmic.c b/sound/soc/intel/boards/sof_sdw_dmic.c index e92176bf0ad4..89b0824b2381 100644 --- a/sound/soc/intel/boards/sof_sdw_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_dmic.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c index cb1118e78e89..b60852339330 100644 --- a/sound/soc/intel/boards/sof_sdw_hdmi.c +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c index a3d0e053b1a6..177cc781ada6 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index 6680dde76682..da354ba83939 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index d3725bb91e43..5515f397a3dd 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 8590a8a8889f..1ded5d9895cf 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c index 321e1cbc03ed..9b298f79e784 100644 --- a/sound/soc/intel/boards/sof_sdw_rt715.c +++ b/sound/soc/intel/boards/sof_sdw_rt715.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index bd352878f89a..2674c9790fa1 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-soc-sst-dsp-objs := sst-dsp.o snd-soc-sst-acpi-objs := sst-acpi.o snd-soc-sst-ipc-objs := sst-ipc.o diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c index f5092bc48364..68758e7a16d8 100644 --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c index ff9d6938b9f6..27b4b73d94d4 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-apci-intel-cfl-match.c - tables and support for CFL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index 7d85bd5aff9f..cdea0c09fe0a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-cml-match.c - tables and support for CML ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index 828980d5630d..6a0bcc1a8429 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c index b9ae0e2c959f..45e07d886013 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-apci-intel-ehl-match.c - tables and support for EHL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c index 60dea358fa04..26cb3b16cdd3 100644 --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c b/sound/soc/intel/common/soc-acpi-intel-hda-match.c index cc972d2ac691..aa9cb522aac9 100644 --- a/sound/soc/intel/common/soc-acpi-intel-hda-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2018, Intel Corporation. /* diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c index 16ec9f382b0f..6927bbbc66fc 100644 --- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-icl-match.c - tables and support for ICL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index 4388a32718d8..859f8a1bd914 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-apci-intel-jsl-match.c - tables and support for JSL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index e200baa11011..a4fbe6707ca7 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-kbl-match.c - tables and support for KBL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c index 42fa40a8d932..26f9ce146523 100644 --- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-skl-match.c - tables and support for SKL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 449d9d2286ae..5a56f4359479 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-apci-intel-tgl-match.c - tables and support for ICL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h index a9176150c6ed..b07df3059926 100644 --- a/sound/soc/intel/common/soc-intel-quirks.h +++ b/sound/soc/intel/common/soc-intel-quirks.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * soc-intel-quirks.h - prototypes for quirk autodetection * diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 48544ff1a3e6..dd39149b89b1 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \ skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o skl-sst-cldma.o \ skl-sst.o bxt-sst.o cnl-sst.o skl-sst-utils.o diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index bd43885f3805..a3a73c26f9aa 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2015-17 Intel Corporation /* diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 8eca2f85c90e..05718dfe6cd2 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o utils.o sof-audio.o diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 7294451cd67c..2d4969c705a4 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/compress.h b/sound/soc/sof/compress.h index 0386844c0bf5..ca8790bd4b13 100644 --- a/sound/soc/sof/compress.h +++ b/sound/soc/sof/compress.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index dfc412e2d956..97d5aca45de8 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 91acfae7935c..94a2cb58ab9a 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index b5c0d6cf72cc..8e15f105d1d5 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 66684d7590f4..8230285baa43 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) config SND_SOC_SOF_IMX_TOPLEVEL bool "SOF support for NXP i.MX audio DSPs" diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile index d9d8dc1765b8..2b933b02bbac 100644 --- a/sound/soc/sof/imx/Makefile +++ b/sound/soc/sof/imx/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-imx8-objs := imx8.o snd-sof-imx8m-objs := imx8m.o diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index b692752b2178..68b2edccd791 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // Copyright 2019 NXP // diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 07451ba4efae..3ac0444dca93 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // Copyright 2020 NXP // diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index cee02a2e00f4..f7e9358f1f06 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-intel-byt-objs := byt.o snd-sof-intel-bdw-objs := bdw.o diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 02218d22e51f..9e29d4fd393a 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index a32a3ef78ec5..99fd0bd7276e 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 29fd1d86156c..f872bb1f2682 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index e427d00eca71..16db0f50d139 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 1d2babdda9dd..789148e5584b 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 7e7e296a3953..c3299be119a1 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-compress.c b/sound/soc/sof/intel/hda-compress.c index 38a1ebec8478..53c08034fa22 100644 --- a/sound/soc/sof/intel/hda-compress.c +++ b/sound/soc/sof/intel/hda-compress.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 6288b2f99540..fa5f0a718901 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 833dc303b394..3934cd6bf87a 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index c780e1e6f895..9e5ff8c18f99 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 6062bb6011fb..c91aa951df22 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-ipc.h b/sound/soc/sof/intel/hda-ipc.h index aef0ceac9803..ade4c3191a39 100644 --- a/sound/soc/sof/intel/hda-ipc.h +++ b/sound/soc/sof/intel/hda-ipc.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 1beaaf5879e2..d762b3e1ce4a 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index a46a6baa1c3f..53a875ac52d6 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 5d386956906f..7f65dcc95811 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index 33b23bd6a01e..1eb746d5adeb 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 337dce3b5def..578ac7b036b0 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index e9825798de77..fe452f0d0ec7 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/intel-ipc.c b/sound/soc/sof/intel/intel-ipc.c index e935f70d611b..310f9168c124 100644 --- a/sound/soc/sof/intel/intel-ipc.c +++ b/sound/soc/sof/intel/intel-ipc.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index daaf3364c177..6fe8b004b50e 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 1c6794918cbb..f7a0353596fb 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 89f35db2577d..4a5b57ecf359 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 5bf67b2aa4e7..ce053ba8f2e8 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/ops.c b/sound/soc/sof/ops.c index 7a27c3b719e7..1a394b4c6a2f 100644 --- a/sound/soc/sof/ops.c +++ b/sound/soc/sof/ops.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index a771500ac442..b21632f5511a 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index e9679fcba428..22fe9d5e932b 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index c410822d9920..1f8f7e33979d 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/probe.c b/sound/soc/sof/probe.c index c38169fe00c5..14509f4d3f86 100644 --- a/sound/soc/sof/probe.c +++ b/sound/soc/sof/probe.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/probe.h b/sound/soc/sof/probe.h index 45daa5552834..b04b728c7224 100644 --- a/sound/soc/sof/probe.h +++ b/sound/soc/sof/probe.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 1278aa95effa..c5eaaa978054 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index fc4ed2a8a914..1c7698f8edd6 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index bf65f31af858..41e2abd077e6 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index c6167597d6fe..f492c5dfa659 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // Copyright 2019 NXP // diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index b5f0221d624f..b13697dab7c0 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 965b9da696d5..a34dbae9f971 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 8ab0fc558054..42d1b1e55e55 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index d815090252f8..69889241a092 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/utils.c b/sound/soc/sof/utils.c index 9831eb57df6c..5539d3afbe8f 100644 --- a/sound/soc/sof/utils.c +++ b/sound/soc/sof/utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. diff --git a/sound/soc/sof/xtensa/Makefile b/sound/soc/sof/xtensa/Makefile index cc89c7472a38..b8376ea04bcf 100644 --- a/sound/soc/sof/xtensa/Makefile +++ b/sound/soc/sof/xtensa/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-xtensa-dsp-objs := core.o diff --git a/sound/soc/sof/xtensa/core.c b/sound/soc/sof/xtensa/core.c index ea08651f0bb3..bbb9a2282ed9 100644 --- a/sound/soc/sof/xtensa/core.c +++ b/sound/soc/sof/xtensa/core.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only 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. From 5c2d0de544c39407bf286d33bdcc1fb06a892d8b Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Sat, 2 May 2020 12:31:19 -0700 Subject: [PATCH 176/428] ALSA: line6: hwdep: add support for O_NONBLOCK opening mode Currently line6 hwdep interface ignores O_NONBLOCK flag when opening device and it renders it somewhat useless when using poll. Check for O_NONBLOCK flag when opening device and don't block read() if it is set. Signed-off-by: Vasily Khoruzhick Link: https://lore.kernel.org/r/20200502193120.79115-2-anarsoul@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/line6/driver.c | 4 ++++ sound/usb/line6/driver.h | 1 + 2 files changed, 5 insertions(+) diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 4f096685ed65..86adf87d57f0 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -550,6 +550,7 @@ static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file) /* NOTE: hwdep layer provides atomicity here */ line6->messages.active = 1; + line6->messages.nonblock = file->f_flags & O_NONBLOCK ? 1 : 0; return 0; } @@ -579,6 +580,9 @@ line6_hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, while (kfifo_len(&line6->messages.fifo) == 0) { mutex_unlock(&line6->messages.read_lock); + if (line6->messages.nonblock) + return -EAGAIN; + rv = wait_event_interruptible( line6->messages.wait_queue, kfifo_len(&line6->messages.fifo) != 0); diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index e5e572ed5f30..1a4e3700c80c 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -163,6 +163,7 @@ struct usb_line6 { struct mutex read_lock; wait_queue_head_t wait_queue; unsigned int active:1; + unsigned int nonblock:1; STRUCT_KFIFO_REC_2(LINE6_BUFSIZE_LISTEN * LINE6_RAW_MESSAGES_MAXCOUNT) fifo; } messages; From c55f5692748cdf7b6eee651dd91f4f3a84307e98 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Sat, 2 May 2020 12:31:20 -0700 Subject: [PATCH 177/428] ALSA: line6: Add poll callback for hwdep At least POD HD500 uses message-based communication, both sides can send messages. Add poll callback so application can wait for device messages without using busy loop. Signed-off-by: Vasily Khoruzhick Link: https://lore.kernel.org/r/20200502193120.79115-3-anarsoul@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/line6/driver.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 86adf87d57f0..7629116f570e 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -630,11 +630,27 @@ line6_hwdep_write(struct snd_hwdep *hwdep, const char __user *data, long count, return rv; } +static __poll_t +line6_hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) +{ + __poll_t rv; + struct usb_line6 *line6 = hwdep->private_data; + + poll_wait(file, &line6->messages.wait_queue, wait); + + mutex_lock(&line6->messages.read_lock); + rv = kfifo_len(&line6->messages.fifo) == 0 ? 0 : EPOLLIN | EPOLLRDNORM; + mutex_unlock(&line6->messages.read_lock); + + return rv; +} + static const struct snd_hwdep_ops hwdep_ops = { .open = line6_hwdep_open, .release = line6_hwdep_release, .read = line6_hwdep_read, .write = line6_hwdep_write, + .poll = line6_hwdep_poll, }; /* Insert into circular buffer */ From bb9b02a4589cee66cdb92eb9b7191d6557afdd6f Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Mon, 4 May 2020 13:46:14 +0530 Subject: [PATCH 178/428] ALSA: hda/tegra: correct number of SDO lines for Tegra194 Tegra194 supports 4 SDO lines but GCAP register indicates 2 lines. Thus it does not reflect the true capability of the HW. This patch presents a workaround by updating NSDO value accordingly in T_AZA_DBG_CFG_2 register. Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1588580176-2801-2-git-send-email-spujar@nvidia.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_tegra.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 773992a07efa..45dc54485f24 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -52,10 +52,21 @@ #define HDA_IPFS_INTR_MASK 0x188 #define HDA_IPFS_EN_INTR (1 << 16) +/* FPCI */ +#define FPCI_DBG_CFG_2 0x10F4 +#define FPCI_GCAP_NSDO_SHIFT 18 +#define FPCI_GCAP_NSDO_MASK (0x3 << FPCI_GCAP_NSDO_SHIFT) + /* max number of SDs */ #define NUM_CAPTURE_SD 1 #define NUM_PLAYBACK_SD 1 +/* + * Tegra194 does not reflect correct number of SDO lines. Below macro + * is used to update the GCAP register to workaround the issue. + */ +#define TEGRA194_NUM_SDO_LINES 4 + struct hda_tegra { struct azx chip; struct device *dev; @@ -275,6 +286,7 @@ static int hda_tegra_init_clk(struct hda_tegra *hda) static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) { + struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); struct hdac_bus *bus = azx_bus(chip); struct snd_card *card = chip->card; int err; @@ -298,6 +310,26 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) bus->irq = irq_id; card->sync_irq = bus->irq; + /* + * Tegra194 has 4 SDO lines and the STRIPE can be used to + * indicate how many of the SDO lines the stream should be + * striped. But GCAP register does not reflect the true + * capability of HW. Below workaround helps to fix this. + * + * GCAP_NSDO is bits 19:18 in T_AZA_DBG_CFG_2, + * 0 for 1 SDO, 1 for 2 SDO, 2 for 4 SDO lines. + */ + if (of_device_is_compatible(np, "nvidia,tegra194-hda")) { + u32 val; + + dev_info(card->dev, "Override SDO lines to %u\n", + TEGRA194_NUM_SDO_LINES); + + val = readl(hda->regs + FPCI_DBG_CFG_2) & ~FPCI_GCAP_NSDO_MASK; + val |= (TEGRA194_NUM_SDO_LINES >> 1) << FPCI_GCAP_NSDO_SHIFT; + writel(val, hda->regs + FPCI_DBG_CFG_2); + } + gcap = azx_readw(chip, GCAP); dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); @@ -408,6 +440,7 @@ static int hda_tegra_create(struct snd_card *card, static const struct of_device_id hda_tegra_match[] = { { .compatible = "nvidia,tegra30-hda" }, + { .compatible = "nvidia,tegra194-hda" }, {}, }; MODULE_DEVICE_TABLE(of, hda_tegra_match); From 67ae482a59e951c346b5a55a756504bc58ce7cfa Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Mon, 4 May 2020 13:46:15 +0530 Subject: [PATCH 179/428] ALSA: hda: add member to store ratio for stripe control Stripe control programming is governed by following formula, which is referenced from the HD Audio specification(Revision 1.0a). { ((num_channels * bits_per_sample) / number of SDOs) >= 8 } Currently above is implemented in snd_hdac_get_stream_stripe_ctl(). This patch introduces a structure member to store the default factor of '8'. If any HW wants to use a different value, this member can be easily updated. Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1588580176-2801-3-git-send-email-spujar@nvidia.com Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 3 +++ sound/hda/hdac_controller.c | 12 ++++++++++++ sound/hda/hdac_stream.c | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index affedc2801c4..d365297b3698 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -364,6 +364,9 @@ struct hdac_bus { /* link management */ struct list_head hlink_list; bool cmd_dma_state; + + /* factor used to derive STRIPE control value */ + unsigned int sdo_limit; }; int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index bc4a8b606020..ac15aa357fbd 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -527,6 +527,18 @@ bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset) } bus->chip_init = true; + + /* + * Default value of '8' is as per the HD audio specification (Rev 1.0a). + * Following relation is used to derive STRIPE control value. + * For sample rate <= 48K: + * { ((num_channels * bits_per_sample) / number of SDOs) >= 8 } + * For sample rate > 48K: + * { ((num_channels * bits_per_sample * rate/48000) / + * number of SDOs) >= 8 } + */ + bus->sdo_limit = 8; + return true; } EXPORT_SYMBOL_GPL(snd_hdac_bus_init_chip); diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index a314b03b4a4c..a38a2af1654f 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -38,7 +38,7 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, else value = (channels * bits_per_sample) / sdo_line; - if (value >= 8) + if (value >= bus->sdo_limit) break; } From 60019d8c650d20a7363285f88f4177dd48d029a7 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Mon, 4 May 2020 13:46:16 +0530 Subject: [PATCH 180/428] ALSA: hda/tegra: workaround playback failure on Tegra194 Tegra194 has 4 SDO lines and with this configuration playback fails for 44.1K/48K, 2-channel and 16-bps. It results in below print, "aplay: pcm_write:2011: write error: Input/output error" Below relation is used to derive stripe control and is referenced from HD Audio Specification: Revision 1.0a. { ((num_channels * bits_per_sample) / number of SDOs) >= 8 } Due to a legacy HW design problem, playback issue is hit while using a stripe value resulting from above formula when ratio is '8'. Thus it is recommended that the ratio must be greater than '8'. Since the number of SDO lines is in powers of 2, next available ratio '16' is used as a limiting factor on Tegra194 to workaround the problem. Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1588580176-2801-4-git-send-email-spujar@nvidia.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_tegra.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 45dc54485f24..0cc5fad1af8a 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -364,6 +364,23 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) /* initialize chip */ azx_init_chip(chip, 1); + /* + * Playback (for 44.1K/48K, 2-channel, 16-bps) fails with + * 4 SDO lines due to legacy design limitation. Following + * is, from HD Audio Specification (Revision 1.0a), used to + * control striping of the stream across multiple SDO lines + * for sample rates <= 48K. + * + * { ((num_channels * bits_per_sample) / number of SDOs) >= 8 } + * + * Due to legacy design issue it is recommended that above + * ratio must be greater than 8. Since number of SDO lines is + * in powers of 2, next available ratio is 16 which can be + * used as a limiting factor here. + */ + if (of_device_is_compatible(np, "nvidia,tegra194-hda")) + chip->bus.core.sdo_limit = 16; + /* codec detection */ if (!bus->codec_mask) { dev_err(card->dev, "no codecs found!\n"); From afcbaa20d662ce8c78b70e953fa8a045c7a243fb Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Mon, 4 May 2020 15:40:06 +0800 Subject: [PATCH 181/428] ASoC: rt1308: Revise the devicetree file mode The patch changes the devicetree file mode correctly. Signed-off-by: Oder Chiou Link: https://lore.kernel.org/r/20200504074007.13002-1-oder_chiou@realtek.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rt1308.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Documentation/devicetree/bindings/sound/rt1308.txt diff --git a/Documentation/devicetree/bindings/sound/rt1308.txt b/Documentation/devicetree/bindings/sound/rt1308.txt old mode 100755 new mode 100644 From 1a446873d7dd3a450f685928ce7f1907bde4583d Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Fri, 1 May 2020 18:44:21 -0500 Subject: [PATCH 182/428] ASoC: max98373: reorder max98373_reset() in resume During S3 test, the following error was observed: [ 726.174237] i2c_designware i2c_designware.0: platform_pm_resume+0x0/0x3d returned 0 after 0 usecs [ 726.184187] max98373 i2c-MX98373:00: calling max98373_resume+0x0/0x30 [snd_soc_max98373] @ 12698, parent: i2c-11 [ 726.195589] max98373 i2c-MX98373:00: Reset command failed. (ret:-16) When calling regmap_update_bits(), since map->reg_update_bits is NULL, _regmap_read() is entered with the following logic: if (!map->cache_bypass) { ret = regcache_read(map, reg, val); if (ret == 0) return 0; } if (map->cache_only) return -EBUSY; regcache_read() hits -EINVAL because MAX98373_R2000_SW_RESET is volatile, as map->cache_only is set by codec suspend, thus -EBUSY is returned. Fix by moving max98373_reset() after cache_only set to false in max98373_resume(). Signed-off-by: Yong Zhi Link: https://lore.kernel.org/r/1588376661-29799-1-git-send-email-yong.zhi@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index cae1def8902d..96718e3a1ad0 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -850,8 +850,8 @@ static int max98373_resume(struct device *dev) { struct max98373_priv *max98373 = dev_get_drvdata(dev); - max98373_reset(max98373, dev); regcache_cache_only(max98373->regmap, false); + max98373_reset(max98373, dev); regcache_sync(max98373->regmap); return 0; } From 454b3766de45f8508b343e509fdde959b4ff289c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 2 May 2020 16:26:46 +0200 Subject: [PATCH 183/428] ASoC: codecs: max9768: update contact email The 'pengutronix' address is defunct for years. Use the proper contact address. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20200502142646.19033-1-wsa@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/max9768.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index d0737db5868a..39dda1b03b3d 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c @@ -220,6 +220,6 @@ static struct i2c_driver max9768_i2c_driver = { }; module_i2c_driver(max9768_i2c_driver); -MODULE_AUTHOR("Wolfram Sang "); +MODULE_AUTHOR("Wolfram Sang "); MODULE_DESCRIPTION("ASoC MAX9768 amplifier driver"); MODULE_LICENSE("GPL v2"); From f2b1e1cbd352129cfdbc1af52059482d74b4e81a Mon Sep 17 00:00:00 2001 From: Chris Garren Date: Mon, 4 May 2020 09:43:20 -0400 Subject: [PATCH 184/428] ASoC: adau7118: Mark the ADAU7118 reset register as volatile Without this the previously written value was written to this reg, which caused the different configuration registers to be reset. Signed-off-by: Chris Garren Link: https://lore.kernel.org/r/1588599820-57994-1-git-send-email-cdgarren@indesign-llc.com Signed-off-by: Mark Brown --- sound/soc/codecs/adau7118-i2c.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/codecs/adau7118-i2c.c b/sound/soc/codecs/adau7118-i2c.c index a8211362fe82..aa7afb3b826d 100644 --- a/sound/soc/codecs/adau7118-i2c.c +++ b/sound/soc/codecs/adau7118-i2c.c @@ -32,6 +32,12 @@ static const struct reg_default adau7118_reg_defaults[] = { { ADAU7118_REG_RESET, 0x00 }, }; +static bool adau7118_volatile(struct device *dev, unsigned int reg) +{ + return (reg == ADAU7118_REG_RESET); +} + + static const struct regmap_config adau7118_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -39,6 +45,7 @@ static const struct regmap_config adau7118_regmap_config = { .num_reg_defaults = ARRAY_SIZE(adau7118_reg_defaults), .cache_type = REGCACHE_RBTREE, .max_register = ADAU7118_REG_RESET, + .volatile_reg = adau7118_volatile, }; static int adau7118_probe_i2c(struct i2c_client *i2c, From c25504ad64fe391acb23dcfab039831c3825c17e Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Mon, 4 May 2020 15:40:07 +0800 Subject: [PATCH 185/428] ASoC: rl6231: Add the K bypass for the PLL parameters The patch adds the K bypass for the PLL parameters. Signed-off-by: Oder Chiou Link: https://lore.kernel.org/r/20200504074007.13002-2-oder_chiou@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rl6231.c | 29 +++++++++++++++++++---------- sound/soc/codecs/rl6231.h | 1 + 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c index d181c217d835..2586d1cafc0c 100644 --- a/sound/soc/codecs/rl6231.c +++ b/sound/soc/codecs/rl6231.c @@ -97,12 +97,13 @@ struct pll_calc_map { int n; int m; bool m_bp; + bool k_bp; }; static const struct pll_calc_map pll_preset_table[] = { - {19200000, 4096000, 23, 14, 1, false}, - {19200000, 24576000, 3, 30, 3, false}, - {3840000, 24576000, 3, 30, 0, true}, + {19200000, 4096000, 23, 14, 1, false, false}, + {19200000, 24576000, 3, 30, 3, false, false}, + {3840000, 24576000, 3, 30, 0, true, false}, }; static unsigned int find_best_div(unsigned int in, @@ -128,7 +129,7 @@ static unsigned int find_best_div(unsigned int in, * rl6231_pll_calc - Calcualte PLL M/N/K code. * @freq_in: external clock provided to codec. * @freq_out: target clock which codec works on. - * @pll_code: Pointer to structure with M, N, K and bypass flag. + * @pll_code: Pointer to structure with M, N, K, m_bypass and k_bypass flag. * * Calcualte M/N/K code to configure PLL for codec. * @@ -143,7 +144,7 @@ int rl6231_pll_calc(const unsigned int freq_in, unsigned int red, pll_out, in_t, out_t, div, div_t; unsigned int red_t = abs(freq_out - freq_in); unsigned int f_in, f_out, f_max; - bool bypass = false; + bool m_bypass = false, k_bypass = false; if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in) return -EINVAL; @@ -154,7 +155,8 @@ int rl6231_pll_calc(const unsigned int freq_in, k = pll_preset_table[i].k; m = pll_preset_table[i].m; n = pll_preset_table[i].n; - bypass = pll_preset_table[i].m_bp; + m_bypass = pll_preset_table[i].m_bp; + k_bypass = pll_preset_table[i].k_bp; pr_debug("Use preset PLL parameter table\n"); goto code_find; } @@ -172,12 +174,14 @@ int rl6231_pll_calc(const unsigned int freq_in, f_in = freq_in / div; f_out = freq_out / div; k = min_k; + if (min_k < -1) + min_k = -1; for (k_t = min_k; k_t <= max_k; k_t++) { for (n_t = 0; n_t <= max_n; n_t++) { in_t = f_in * (n_t + 2); pll_out = f_out * (k_t + 2); if (in_t == pll_out) { - bypass = true; + m_bypass = true; n = n_t; k = k_t; goto code_find; @@ -185,7 +189,7 @@ int rl6231_pll_calc(const unsigned int freq_in, out_t = in_t / (k_t + 2); red = abs(f_out - out_t); if (red < red_t) { - bypass = true; + m_bypass = true; n = n_t; m = 0; k = k_t; @@ -197,7 +201,7 @@ int rl6231_pll_calc(const unsigned int freq_in, out_t = in_t / ((m_t + 2) * (k_t + 2)); red = abs(f_out - out_t); if (red < red_t) { - bypass = false; + m_bypass = false; n = n_t; m = m_t; k = k_t; @@ -211,8 +215,13 @@ int rl6231_pll_calc(const unsigned int freq_in, pr_debug("Only get approximation about PLL\n"); code_find: + if (k == -1) { + k_bypass = true; + k = 0; + } - pll_code->m_bp = bypass; + pll_code->m_bp = m_bypass; + pll_code->k_bp = k_bypass; pll_code->m_code = m; pll_code->n_code = n; pll_code->k_code = k; diff --git a/sound/soc/codecs/rl6231.h b/sound/soc/codecs/rl6231.h index 6d8ed0377296..928082750860 100644 --- a/sound/soc/codecs/rl6231.h +++ b/sound/soc/codecs/rl6231.h @@ -18,6 +18,7 @@ struct rl6231_pll_code { bool m_bp; /* Indicates bypass m code or not. */ + bool k_bp; /* Indicates bypass k code or not. */ int m_code; int n_code; int k_code; From d696a61413b405a13bbe04f31e6f4531a426fee7 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 4 May 2020 19:20:13 +0800 Subject: [PATCH 186/428] ASoC: rt1015: Add condition to prevent SoC providing bclk in ratio of 50 times of sample rate. Add condition to prevent SoC providing bclk in ratio of 50 times of sample rate. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20200504112013.2499-1-jack.yu@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 27 +++++++++++++++++++++++++++ sound/soc/codecs/rt1015.h | 1 + 2 files changed, 28 insertions(+) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index bb310bc7febd..5eb07a430ae3 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -780,6 +780,14 @@ static int rt1015_set_component_pll(struct snd_soc_component *component, freq_out == rt1015->pll_out) return 0; + if (source == RT1015_PLL_S_BCLK) { + if (rt1015->bclk_ratio == 0) { + dev_err(component->dev, + "Can not support bclk ratio as 0.\n"); + return -EINVAL; + } + } + switch (source) { case RT1015_PLL_S_MCLK: snd_soc_component_update_bits(component, RT1015_CLK2, @@ -819,12 +827,30 @@ static int rt1015_set_component_pll(struct snd_soc_component *component, return 0; } +static int rt1015_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) +{ + struct snd_soc_component *component = dai->component; + struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s ratio=%d\n", __func__, ratio); + + rt1015->bclk_ratio = ratio; + + if (ratio == 50) { + dev_dbg(component->dev, "Unsupport bclk ratio\n"); + return -EINVAL; + } + + return 0; +} + static int rt1015_probe(struct snd_soc_component *component) { struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); rt1015->component = component; + rt1015->bclk_ratio = 0; snd_soc_component_write(component, RT1015_BAT_RPO_STEP1, 0x061c); return 0; @@ -844,6 +870,7 @@ static void rt1015_remove(struct snd_soc_component *component) static struct snd_soc_dai_ops rt1015_aif_dai_ops = { .hw_params = rt1015_hw_params, .set_fmt = rt1015_set_dai_fmt, + .set_bclk_ratio = rt1015_set_bclk_ratio, }; static struct snd_soc_dai_driver rt1015_dai[] = { diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index ef3745a4faae..6fbe802082c4 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -362,6 +362,7 @@ struct rt1015_priv { int sysclk_src; int lrck; int bclk; + int bclk_ratio; int id; int pll_src; int pll_in; From 952c0e260f8dd44ddb6ff0e260130f1906f7bcf3 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Mon, 4 May 2020 14:59:47 +0800 Subject: [PATCH 187/428] ASoC: qcom: Use the defined variable to simplify code Use the defined variable "dev" to make the code cleaner. Signed-off-by: Zhang Shengju Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200504065947.12172-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-apq8016.c | 9 ++++---- sound/soc/qcom/lpass-cpu.c | 39 ++++++++++++++++------------------ 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c index 6575da549237..b3610d05b651 100644 --- a/sound/soc/qcom/lpass-apq8016.c +++ b/sound/soc/qcom/lpass-apq8016.c @@ -166,28 +166,27 @@ static int apq8016_lpass_init(struct platform_device *pdev) drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk"); if (IS_ERR(drvdata->pcnoc_mport_clk)) { - dev_err(&pdev->dev, "error getting pcnoc-mport-clk: %ld\n", + dev_err(dev, "error getting pcnoc-mport-clk: %ld\n", PTR_ERR(drvdata->pcnoc_mport_clk)); return PTR_ERR(drvdata->pcnoc_mport_clk); } ret = clk_prepare_enable(drvdata->pcnoc_mport_clk); if (ret) { - dev_err(&pdev->dev, "Error enabling pcnoc-mport-clk: %d\n", - ret); + dev_err(dev, "Error enabling pcnoc-mport-clk: %d\n", ret); return ret; } drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk"); if (IS_ERR(drvdata->pcnoc_sway_clk)) { - dev_err(&pdev->dev, "error getting pcnoc-sway-clk: %ld\n", + dev_err(dev, "error getting pcnoc-sway-clk: %ld\n", PTR_ERR(drvdata->pcnoc_sway_clk)); return PTR_ERR(drvdata->pcnoc_sway_clk); } ret = clk_prepare_enable(drvdata->pcnoc_sway_clk); if (ret) { - dev_err(&pdev->dev, "Error enabling pcnoc_sway_clk: %d\n", ret); + dev_err(dev, "Error enabling pcnoc_sway_clk: %d\n", ret); return ret; } diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index dbce7e92baf3..c6d26395f13b 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -425,12 +425,11 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); if (dsp_of_node) { - dev_err(&pdev->dev, "DSP exists and holds audio resources\n"); + dev_err(dev, "DSP exists and holds audio resources\n"); return -EBUSY; } - drvdata = devm_kzalloc(&pdev->dev, sizeof(struct lpass_data), - GFP_KERNEL); + drvdata = devm_kzalloc(dev, sizeof(struct lpass_data), GFP_KERNEL); if (!drvdata) return -ENOMEM; platform_set_drvdata(pdev, drvdata); @@ -444,9 +443,9 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); - drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); + drvdata->lpaif = devm_ioremap_resource(dev, res); if (IS_ERR((void const __force *)drvdata->lpaif)) { - dev_err(&pdev->dev, "error mapping reg resource: %ld\n", + dev_err(dev, "error mapping reg resource: %ld\n", PTR_ERR((void const __force *)drvdata->lpaif)); return PTR_ERR((void const __force *)drvdata->lpaif); } @@ -455,10 +454,10 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) variant->wrdma_channels + variant->wrdma_channel_start); - drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, + drvdata->lpaif_map = devm_regmap_init_mmio(dev, drvdata->lpaif, &lpass_cpu_regmap_config); if (IS_ERR(drvdata->lpaif_map)) { - dev_err(&pdev->dev, "error initializing regmap: %ld\n", + dev_err(dev, "error initializing regmap: %ld\n", PTR_ERR(drvdata->lpaif_map)); return PTR_ERR(drvdata->lpaif_map); } @@ -468,10 +467,10 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) for (i = 0; i < variant->num_dai; i++) { dai_id = variant->dai_driver[i].id; - drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(&pdev->dev, + drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(dev, variant->dai_osr_clk_names[i]); if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) { - dev_warn(&pdev->dev, + dev_warn(dev, "%s() error getting optional %s: %ld\n", __func__, variant->dai_osr_clk_names[i], @@ -480,10 +479,10 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) drvdata->mi2s_osr_clk[dai_id] = NULL; } - drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(&pdev->dev, + drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(dev, variant->dai_bit_clk_names[i]); if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) { - dev_err(&pdev->dev, + dev_err(dev, "error getting %s: %ld\n", variant->dai_bit_clk_names[i], PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); @@ -491,41 +490,39 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) } } - drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); + drvdata->ahbix_clk = devm_clk_get(dev, "ahbix-clk"); if (IS_ERR(drvdata->ahbix_clk)) { - dev_err(&pdev->dev, "error getting ahbix-clk: %ld\n", + dev_err(dev, "error getting ahbix-clk: %ld\n", PTR_ERR(drvdata->ahbix_clk)); return PTR_ERR(drvdata->ahbix_clk); } ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); if (ret) { - dev_err(&pdev->dev, "error setting rate on ahbix_clk: %d\n", - ret); + dev_err(dev, "error setting rate on ahbix_clk: %d\n", ret); return ret; } - dev_dbg(&pdev->dev, "set ahbix_clk rate to %lu\n", + dev_dbg(dev, "set ahbix_clk rate to %lu\n", clk_get_rate(drvdata->ahbix_clk)); ret = clk_prepare_enable(drvdata->ahbix_clk); if (ret) { - dev_err(&pdev->dev, "error enabling ahbix_clk: %d\n", ret); + dev_err(dev, "error enabling ahbix_clk: %d\n", ret); return ret; } - ret = devm_snd_soc_register_component(&pdev->dev, + ret = devm_snd_soc_register_component(dev, &lpass_cpu_comp_driver, variant->dai_driver, variant->num_dai); if (ret) { - dev_err(&pdev->dev, "error registering cpu driver: %d\n", ret); + dev_err(dev, "error registering cpu driver: %d\n", ret); goto err_clk; } ret = asoc_qcom_lpass_platform_register(pdev); if (ret) { - dev_err(&pdev->dev, "error registering platform driver: %d\n", - ret); + dev_err(dev, "error registering platform driver: %d\n", ret); goto err_clk; } From dbab677f324dcf26dc8c443e3ff39a4eaa6dcacc Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 22 Nov 2019 18:30:13 +0800 Subject: [PATCH 188/428] ASoC: wm8524: Add support S32_LE Allow 32bit sample with this codec. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/cff745cc041c5208910821f0740f988926af8a66.1574418380.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8524.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8524.c b/sound/soc/codecs/wm8524.c index 91e3d1570c45..4e9ab542f648 100644 --- a/sound/soc/codecs/wm8524.c +++ b/sound/soc/codecs/wm8524.c @@ -159,7 +159,9 @@ static int wm8524_mute_stream(struct snd_soc_dai *dai, int mute, int stream) #define WM8524_RATES SNDRV_PCM_RATE_8000_192000 -#define WM8524_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) +#define WM8524_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops wm8524_dai_ops = { .startup = wm8524_startup, From 50f0bf550f835f0a4251fa99894db09234c12075 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Tue, 5 May 2020 11:03:52 +0800 Subject: [PATCH 189/428] ALSA: hda: Use dev_to_hdac_dev macro Use dev_to_hdac_dev() instead of container_of(). No functional change intended. Signed-off-by: Kai-Heng Feng Link: https://lore.kernel.org/r/20200505030357.28004-1-kai.heng.feng@canonical.com Signed-off-by: Takashi Iwai --- sound/hda/ext/hdac_ext_bus.c | 2 +- sound/hda/hdac_device.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 73bfa71845f6..d0a604c939df 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -62,7 +62,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit); static void default_release(struct device *dev) { - snd_hdac_ext_bus_device_exit(container_of(dev, struct hdac_device, dev)); + snd_hdac_ext_bus_device_exit(dev_to_hdac_dev(dev)); } /** diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index e3119f5cb0d5..333220f0f8af 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -20,7 +20,7 @@ static int get_codec_vendor_name(struct hdac_device *codec); static void default_release(struct device *dev) { - snd_hdac_device_exit(container_of(dev, struct hdac_device, dev)); + snd_hdac_device_exit(dev_to_hdac_dev(dev)); } /** From 8c11827bba724046fec50a1f16a205bbea3eeb08 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Tue, 5 May 2020 11:03:53 +0800 Subject: [PATCH 190/428] ALSA: hda: Use hdac_to_hda_codec macro Use hdac_to_hda_codec() instead of container_of(). No functional change intended. Signed-off-by: Kai-Heng Feng Link: https://lore.kernel.org/r/20200505030357.28004-2-kai.heng.feng@canonical.com Signed-off-by: Takashi Iwai --- include/sound/hda_codec.h | 4 ++++ sound/pci/hda/patch_hdmi.c | 12 ++++++------ sound/soc/codecs/hdac_hda.h | 4 ---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 225154a4f2ed..8a32060e3d8d 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -288,6 +288,10 @@ struct hda_codec { #define dev_to_hda_codec(_dev) container_of(_dev, struct hda_codec, core.dev) #define hda_codec_dev(_dev) (&(_dev)->core.dev) +#define hdac_to_hda_priv(_hdac) \ + container_of(_hdac, struct hdac_hda_priv, codec.core) +#define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core) + #define list_for_each_codec(c, bus) \ list_for_each_entry(c, &(bus)->core.codec_list, core.list) #define list_for_each_codec_safe(c, n, bus) \ diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 4eff16053bd5..f21b66abb271 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2022,7 +2022,7 @@ static const struct hda_pcm_ops generic_ops = { static int hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); @@ -2035,7 +2035,7 @@ static int hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx, unsigned char *chmap) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); @@ -2049,7 +2049,7 @@ static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx, static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, unsigned char *chmap, int prepared) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); @@ -2065,7 +2065,7 @@ static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, static bool is_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); @@ -3783,7 +3783,7 @@ static int atihdmi_paired_chmap_validate(struct hdac_chmap *chmap, static int atihdmi_pin_set_slot_channel(struct hdac_device *hdac, hda_nid_t pin_nid, int hdmi_slot, int stream_channel) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); int verb; int ati_channel_setup = 0; @@ -3819,7 +3819,7 @@ static int atihdmi_pin_set_slot_channel(struct hdac_device *hdac, static int atihdmi_pin_get_slot_channel(struct hdac_device *hdac, hda_nid_t pin_nid, int asp_slot) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); bool was_odd = false; int ati_asp_slot = asp_slot; int verb; diff --git a/sound/soc/codecs/hdac_hda.h b/sound/soc/codecs/hdac_hda.h index 598b07d9b6fe..d0efc5e254ae 100644 --- a/sound/soc/codecs/hdac_hda.h +++ b/sound/soc/codecs/hdac_hda.h @@ -28,10 +28,6 @@ struct hdac_hda_priv { bool need_display_power; }; -#define hdac_to_hda_priv(_hdac) \ - container_of(_hdac, struct hdac_hda_priv, codec.core) -#define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core) - struct hdac_ext_bus_ops *snd_soc_hdac_hda_get_ops(void); #endif /* __HDAC_HDA_H__ */ From d5797ede0818b24252f79497e1c7e1245c328f6b Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Sat, 25 Apr 2020 20:46:56 +0200 Subject: [PATCH 191/428] dt-bindings: sound: lpass-cpu: Document DAI subnodes The lpass-cpu driver now allows configuring the MI2S SD lines by defining subnodes for one of the DAIs. Document this in the device tree bindings. Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20200425184657.121991-1-stephan@gerhold.net Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-cpu.txt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt index 21c648328be9..32c2cdb3d32f 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt @@ -30,6 +30,8 @@ Required properties: - reg : Must contain an address for each entry in reg-names. - reg-names : A list which must include the following entries: * "lpass-lpaif" +- #address-cells : Must be 1 +- #size-cells : Must be 0 @@ -37,6 +39,20 @@ Optional properties: - qcom,adsp : Phandle for the audio DSP node +By default, the driver uses up to 4 MI2S SD lines, for a total of 8 channels. +The SD lines to use can be configured by adding subnodes for each of the DAIs. + +Required properties for each DAI (represented by a subnode): +- reg : Must be one of the DAI IDs + (usually part of dt-bindings header) +- qcom,playback-sd-lines: List of serial data lines to use for playback + Each SD line should be represented by a number from 0-3. +- qcom,capture-sd-lines : List of serial data lines to use for capture + Each SD line should be represented by a number from 0-3. + +Note that adding a subnode changes the default to "no lines configured", +so both playback and capture lines should be configured when a subnode is added. + Example: lpass@28100000 { @@ -51,4 +67,13 @@ lpass@28100000 { reg = <0x28100000 0x10000>; reg-names = "lpass-lpaif"; qcom,adsp = <&adsp>; + + #address-cells = <1>; + #size-cells = <0>; + + /* Optional to set different MI2S SD lines */ + dai@3 { + reg = ; + qcom,playback-sd-lines = <0 1>; + }; }; From 4ff028f6c1087bcaf1ee970d4ef43730ed0aaa8c Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Sat, 25 Apr 2020 20:46:57 +0200 Subject: [PATCH 192/428] ASoC: qcom: lpass-cpu: Make I2S SD lines configurable The LPASS hardware allows configuring the MI2S SD lines to use when playing/recording audio. However, at the moment the lpass-cpu driver has SD0 hard-coded for mono/stereo (or additional fixed SD lines for more channels). For weird reasons there seems to be hardware that uses one of the other SD lines for mono/stereo. For example, some Samsung devices use an external Speaker amplifier connected to Quaternary MI2S. For some reason, the SD line for audio playback was connected to SD1 rather than SD0. (I have no idea why...) At the moment, the lpass-cpu driver cannot be configured to work for the Speaker on these devices. The q6afe driver already allows configuring the MI2S SD lines through the "qcom,sd-lines" device tree property, but this works only when routing audio through the ADSP. This commit adds a very similar configuration for the lpass-cpu driver. It is now possible to add additional subnodes to the lpass device in the device tree, to configure the SD lines for playback and/or capture. E.g. for the Samsung devices mentioned above: &lpass { dai@3 { reg = ; qcom,playback-sd-lines = <1>; }; }; qcom,playback/capture-sd-lines takes a list of SD lines (0-3) in the same format as the q6afe driver. (The difference here is that q6afe has separate DAIs for playback/capture, while lpass-cpu has one for both...) For backwards compatibility with older device trees, the lpass-cpu driver defaults to LPAIF_I2SCTL_MODE_8CH if the subnode for a DAI is missing. This is equivalent to the previous behavior: Up to 8 channels can be configured, and SD0/QUAT01 will be chosen when setting up a stream with fewer channels. This allows the speaker to work on Samsung MSM8916 devices that use an external speaker amplifier. Signed-off-by: Stephan Gerhold Cc: Srinivas Kandagatla Link: https://lore.kernel.org/r/20200425184657.121991-2-stephan@gerhold.net Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 204 +++++++++++++++++++++++-------- sound/soc/qcom/lpass-lpaif-reg.h | 30 ++--- sound/soc/qcom/lpass.h | 4 + 3 files changed, 170 insertions(+), 68 deletions(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index c6d26395f13b..e00a4af29c13 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -19,6 +19,16 @@ #include "lpass-lpaif-reg.h" #include "lpass.h" +#define LPASS_CPU_MAX_MI2S_LINES 4 +#define LPASS_CPU_I2S_SD0_MASK BIT(0) +#define LPASS_CPU_I2S_SD1_MASK BIT(1) +#define LPASS_CPU_I2S_SD2_MASK BIT(2) +#define LPASS_CPU_I2S_SD3_MASK BIT(3) +#define LPASS_CPU_I2S_SD0_1_MASK GENMASK(1, 0) +#define LPASS_CPU_I2S_SD2_3_MASK GENMASK(3, 2) +#define LPASS_CPU_I2S_SD0_1_2_MASK GENMASK(2, 0) +#define LPASS_CPU_I2S_SD0_1_2_3_MASK GENMASK(3, 0) + static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { @@ -72,6 +82,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, snd_pcm_format_t format = params_format(params); unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); + unsigned int mode; unsigned int regval; int bitwidth, ret; @@ -99,60 +110,84 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + mode = drvdata->mi2s_playback_sd_mode[dai->driver->id]; + else + mode = drvdata->mi2s_capture_sd_mode[dai->driver->id]; + + if (!mode) { + dev_err(dai->dev, "no line is assigned\n"); + return -EINVAL; + } + + switch (channels) { + case 1: + case 2: + switch (mode) { + case LPAIF_I2SCTL_MODE_QUAD01: + case LPAIF_I2SCTL_MODE_6CH: + case LPAIF_I2SCTL_MODE_8CH: + mode = LPAIF_I2SCTL_MODE_SD0; + break; + case LPAIF_I2SCTL_MODE_QUAD23: + mode = LPAIF_I2SCTL_MODE_SD2; + break; + } + + break; + case 4: + if (mode < LPAIF_I2SCTL_MODE_QUAD01) { + dev_err(dai->dev, "cannot configure 4 channels with mode %d\n", + mode); + return -EINVAL; + } + + switch (mode) { + case LPAIF_I2SCTL_MODE_6CH: + case LPAIF_I2SCTL_MODE_8CH: + mode = LPAIF_I2SCTL_MODE_QUAD01; + break; + } + break; + case 6: + if (mode < LPAIF_I2SCTL_MODE_6CH) { + dev_err(dai->dev, "cannot configure 6 channels with mode %d\n", + mode); + return -EINVAL; + } + + switch (mode) { + case LPAIF_I2SCTL_MODE_8CH: + mode = LPAIF_I2SCTL_MODE_6CH; + break; + } + break; + case 8: + if (mode < LPAIF_I2SCTL_MODE_8CH) { + dev_err(dai->dev, "cannot configure 8 channels with mode %d\n", + mode); + return -EINVAL; + } + break; + default: + dev_err(dai->dev, "invalid channels given: %u\n", channels); + return -EINVAL; + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - switch (channels) { - case 1: - regval |= LPAIF_I2SCTL_SPKMODE_SD0; + regval |= LPAIF_I2SCTL_SPKMODE(mode); + + if (channels >= 2) + regval |= LPAIF_I2SCTL_SPKMONO_STEREO; + else regval |= LPAIF_I2SCTL_SPKMONO_MONO; - break; - case 2: - regval |= LPAIF_I2SCTL_SPKMODE_SD0; - regval |= LPAIF_I2SCTL_SPKMONO_STEREO; - break; - case 4: - regval |= LPAIF_I2SCTL_SPKMODE_QUAD01; - regval |= LPAIF_I2SCTL_SPKMONO_STEREO; - break; - case 6: - regval |= LPAIF_I2SCTL_SPKMODE_6CH; - regval |= LPAIF_I2SCTL_SPKMONO_STEREO; - break; - case 8: - regval |= LPAIF_I2SCTL_SPKMODE_8CH; - regval |= LPAIF_I2SCTL_SPKMONO_STEREO; - break; - default: - dev_err(dai->dev, "invalid channels given: %u\n", - channels); - return -EINVAL; - } } else { - switch (channels) { - case 1: - regval |= LPAIF_I2SCTL_MICMODE_SD0; + regval |= LPAIF_I2SCTL_MICMODE(mode); + + if (channels >= 2) + regval |= LPAIF_I2SCTL_MICMONO_STEREO; + else regval |= LPAIF_I2SCTL_MICMONO_MONO; - break; - case 2: - regval |= LPAIF_I2SCTL_MICMODE_SD0; - regval |= LPAIF_I2SCTL_MICMONO_STEREO; - break; - case 4: - regval |= LPAIF_I2SCTL_MICMODE_QUAD01; - regval |= LPAIF_I2SCTL_MICMONO_STEREO; - break; - case 6: - regval |= LPAIF_I2SCTL_MICMODE_6CH; - regval |= LPAIF_I2SCTL_MICMONO_STEREO; - break; - case 8: - regval |= LPAIF_I2SCTL_MICMODE_8CH; - regval |= LPAIF_I2SCTL_MICMONO_STEREO; - break; - default: - dev_err(dai->dev, "invalid channels given: %u\n", - channels); - return -EINVAL; - } } ret = regmap_write(drvdata->lpaif_map, @@ -413,6 +448,73 @@ static struct regmap_config lpass_cpu_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static unsigned int of_lpass_cpu_parse_sd_lines(struct device *dev, + struct device_node *node, + const char *name) +{ + unsigned int lines[LPASS_CPU_MAX_MI2S_LINES]; + unsigned int sd_line_mask = 0; + int num_lines, i; + + num_lines = of_property_read_variable_u32_array(node, name, lines, 0, + LPASS_CPU_MAX_MI2S_LINES); + if (num_lines < 0) + return LPAIF_I2SCTL_MODE_NONE; + + for (i = 0; i < num_lines; i++) + sd_line_mask |= BIT(lines[i]); + + switch (sd_line_mask) { + case LPASS_CPU_I2S_SD0_MASK: + return LPAIF_I2SCTL_MODE_SD0; + case LPASS_CPU_I2S_SD1_MASK: + return LPAIF_I2SCTL_MODE_SD1; + case LPASS_CPU_I2S_SD2_MASK: + return LPAIF_I2SCTL_MODE_SD2; + case LPASS_CPU_I2S_SD3_MASK: + return LPAIF_I2SCTL_MODE_SD3; + case LPASS_CPU_I2S_SD0_1_MASK: + return LPAIF_I2SCTL_MODE_QUAD01; + case LPASS_CPU_I2S_SD2_3_MASK: + return LPAIF_I2SCTL_MODE_QUAD23; + case LPASS_CPU_I2S_SD0_1_2_MASK: + return LPAIF_I2SCTL_MODE_6CH; + case LPASS_CPU_I2S_SD0_1_2_3_MASK: + return LPAIF_I2SCTL_MODE_8CH; + default: + dev_err(dev, "Unsupported SD line mask: %#x\n", sd_line_mask); + return LPAIF_I2SCTL_MODE_NONE; + } +} + +static void of_lpass_cpu_parse_dai_data(struct device *dev, + struct lpass_data *data) +{ + struct device_node *node; + int ret, id; + + /* Allow all channels by default for backwards compatibility */ + for (id = 0; id < data->variant->num_dai; id++) { + data->mi2s_playback_sd_mode[id] = LPAIF_I2SCTL_MODE_8CH; + data->mi2s_capture_sd_mode[id] = LPAIF_I2SCTL_MODE_8CH; + } + + for_each_child_of_node(dev->of_node, node) { + ret = of_property_read_u32(node, "reg", &id); + if (ret || id < 0 || id >= data->variant->num_dai) { + dev_err(dev, "valid dai id not found: %d\n", ret); + continue; + } + + data->mi2s_playback_sd_mode[id] = + of_lpass_cpu_parse_sd_lines(dev, node, + "qcom,playback-sd-lines"); + data->mi2s_capture_sd_mode[id] = + of_lpass_cpu_parse_sd_lines(dev, node, + "qcom,capture-sd-lines"); + } +} + int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) { struct lpass_data *drvdata; @@ -441,6 +543,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) drvdata->variant = (struct lpass_variant *)match->data; variant = drvdata->variant; + of_lpass_cpu_parse_dai_data(dev, drvdata); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); drvdata->lpaif = devm_ioremap_resource(dev, res); diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h index 3d74ae123e9d..72a3e2f69572 100644 --- a/sound/soc/qcom/lpass-lpaif-reg.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -22,17 +22,19 @@ #define LPAIF_I2SCTL_SPKEN_DISABLE (0 << LPAIF_I2SCTL_SPKEN_SHIFT) #define LPAIF_I2SCTL_SPKEN_ENABLE (1 << LPAIF_I2SCTL_SPKEN_SHIFT) +#define LPAIF_I2SCTL_MODE_NONE 0 +#define LPAIF_I2SCTL_MODE_SD0 1 +#define LPAIF_I2SCTL_MODE_SD1 2 +#define LPAIF_I2SCTL_MODE_SD2 3 +#define LPAIF_I2SCTL_MODE_SD3 4 +#define LPAIF_I2SCTL_MODE_QUAD01 5 +#define LPAIF_I2SCTL_MODE_QUAD23 6 +#define LPAIF_I2SCTL_MODE_6CH 7 +#define LPAIF_I2SCTL_MODE_8CH 8 + #define LPAIF_I2SCTL_SPKMODE_MASK 0x3C00 #define LPAIF_I2SCTL_SPKMODE_SHIFT 10 -#define LPAIF_I2SCTL_SPKMODE_NONE (0 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_SD0 (1 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_SD1 (2 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_SD2 (3 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_SD3 (4 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_QUAD01 (5 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_QUAD23 (6 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_6CH (7 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_8CH (8 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE(mode) ((mode) << LPAIF_I2SCTL_SPKMODE_SHIFT) #define LPAIF_I2SCTL_SPKMONO_MASK 0x0200 #define LPAIF_I2SCTL_SPKMONO_SHIFT 9 @@ -46,15 +48,7 @@ #define LPAIF_I2SCTL_MICMODE_MASK GENMASK(7, 4) #define LPAIF_I2SCTL_MICMODE_SHIFT 4 -#define LPAIF_I2SCTL_MICMODE_NONE (0 << LPAIF_I2SCTL_MICMODE_SHIFT) -#define LPAIF_I2SCTL_MICMODE_SD0 (1 << LPAIF_I2SCTL_MICMODE_SHIFT) -#define LPAIF_I2SCTL_MICMODE_SD1 (2 << LPAIF_I2SCTL_MICMODE_SHIFT) -#define LPAIF_I2SCTL_MICMODE_SD2 (3 << LPAIF_I2SCTL_MICMODE_SHIFT) -#define LPAIF_I2SCTL_MICMODE_SD3 (4 << LPAIF_I2SCTL_MICMODE_SHIFT) -#define LPAIF_I2SCTL_MICMODE_QUAD01 (5 << LPAIF_I2SCTL_MICMODE_SHIFT) -#define LPAIF_I2SCTL_MICMODE_QUAD23 (6 << LPAIF_I2SCTL_MICMODE_SHIFT) -#define LPAIF_I2SCTL_MICMODE_6CH (7 << LPAIF_I2SCTL_MICMODE_SHIFT) -#define LPAIF_I2SCTL_MICMODE_8CH (8 << LPAIF_I2SCTL_MICMODE_SHIFT) +#define LPAIF_I2SCTL_MICMODE(mode) ((mode) << LPAIF_I2SCTL_MICMODE_SHIFT) #define LPAIF_I2SCTL_MIMONO_MASK GENMASK(3, 3) #define LPAIF_I2SCTL_MICMONO_SHIFT 3 diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 17113d380dcc..bd19ec57c73d 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -29,6 +29,10 @@ struct lpass_data { /* MI2S bit clock (derived from system clock by a divider */ struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS]; + /* MI2S SD lines to use for playback/capture */ + unsigned int mi2s_playback_sd_mode[LPASS_MAX_MI2S_PORTS]; + unsigned int mi2s_capture_sd_mode[LPASS_MAX_MI2S_PORTS]; + /* low-power audio interface (LPAIF) registers */ void __iomem *lpaif; From 79263c3bceb738567ba96bef4940ac58c07a415c Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Wed, 6 May 2020 14:17:16 +0800 Subject: [PATCH 193/428] ALSA: hda: Return true,false for return type bool Fix the following coccicheck warning: include/sound/hdaudio.h:210:73-74: WARNING: return of 0/1 in function 'snd_hdac_is_in_pm' with return type bool include/sound/hdaudio.h:211:76-77: WARNING: return of 0/1 in function 'snd_hdac_is_power_on' with return type bool Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200506061716.19209-1-yanaijie@huawei.com Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index d365297b3698..10945963d727 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -207,8 +207,8 @@ static inline int snd_hdac_power_down_pm(struct hdac_device *codec) { return 0; static inline int snd_hdac_keep_power_up(struct hdac_device *codec) { return 0; } static inline void snd_hdac_enter_pm(struct hdac_device *codec) {} static inline void snd_hdac_leave_pm(struct hdac_device *codec) {} -static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return 0; } -static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return 1; } +static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return false; } +static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return true; } #endif /* From 5a8117840a8c654c3cdf2f465e9406112d7e492d Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Wed, 6 May 2020 15:56:00 +0530 Subject: [PATCH 194/428] ASoC: amd :High hw_level while simultaneous capture Simultaneous capture on dmic and headset mic is having issue with high hw_level being reported. Issue Can be reproduced by: arecord -D hw:2,0 -f dat -d 60 /tmp/test0 & arecord -D hw:2,2 -f dat -d 60 /tmp/test1 & cat /proc/asound/card2/pcm?c/sub0/status Actual issue is : When we open one capture stream on one instance lets say I2S_SP and then once again if we open other capture on other instance lets say I2S_BT while first capture is in progress and when we try to read the status of both running instances by below command cat /proc/asound/card2/pcm?c/sub0/status we observe that avail_max is being doubled on first opened capture(I2S_SP in the example). This is because our previous implementation was like when any instance is opened it gets initialized in dma_open irrespective of on what instance it called open. For example: First I2S_SP called opened it initializes both SP/BT capture streams irrespective of on which instance the stream opened.next time I2S_BT called opened and it initializes both SP/BT this corrupts the behaviour . So with this patch the stream gets initialized only on specific instance when ever it gets opened calls hw_params. This rectifies the issue. Signed-off-by: Ravulapati Vishnu vardhan rao Signed-off-by: Akshu Agrawal Link: https://lore.kernel.org/r/20200506102602.140790-1-akshu.agrawal@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-pcm-dma.c | 37 +++++++++++++++++++---------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index e362f0bc9e46..a36c5cb848cd 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -241,14 +241,6 @@ static int acp3x_dma_open(struct snd_soc_component *component, adata->i2ssp_play_stream && !adata->i2ssp_capture_stream) rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - adata->play_stream = substream; - adata->i2ssp_play_stream = substream; - } else { - adata->capture_stream = substream; - adata->i2ssp_capture_stream = substream; - } - i2s_data->acp3x_base = adata->acp3x_base; runtime->private_data = i2s_data; return ret; @@ -263,23 +255,42 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component, struct snd_soc_pcm_runtime *prtd; struct snd_soc_card *card; struct acp3x_platform_info *pinfo; + struct i2s_dev_data *adata; u64 size; prtd = substream->private_data; card = prtd->card; pinfo = snd_soc_card_get_drvdata(card); + adata = dev_get_drvdata(component->dev); rtd = substream->runtime->private_data; if (!rtd) return -EINVAL; - if (pinfo) - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + if (pinfo) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { rtd->i2s_instance = pinfo->play_i2s_instance; - else + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + adata->play_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_play_stream = substream; + } + } else { rtd->i2s_instance = pinfo->cap_i2s_instance; - else + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + adata->capture_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_capture_stream = substream; + } + } + } else { pr_err("pinfo failed\n"); - + } size = params_buffer_bytes(params); rtd->dma_addr = substream->dma_buffer.addr; rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); From adb69968074a22376074aaa7f7971d93636b4332 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Wed, 6 May 2020 22:30:09 +0800 Subject: [PATCH 195/428] ASoC: mediatek: Fix error handling If the function platform_get_irq() failed, the negative value returned will not be detected here. So fix error handling in mt6797_afe_pcm_dev_probe(). And when get irq failed, the function platform_get_irq() logs an error message, so remove redundant message here. Signed-off-by: Zhang Shengju Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200506143009.13368-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index 7f930556d961..7f3ac04b9425 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c @@ -807,10 +807,9 @@ static int mt6797_afe_pcm_dev_probe(struct platform_device *pdev) /* request irq */ irq_id = platform_get_irq(pdev, 0); - if (!irq_id) { - dev_err(dev, "%pOFn no irq found\n", dev->of_node); - return -ENXIO; - } + if (irq_id < 0) + return irq_id; + ret = devm_request_irq(dev, irq_id, mt6797_afe_irq_handler, IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); if (ret) { From 59f00717bc09cc30cc61c05b1790db430357ced2 Mon Sep 17 00:00:00 2001 From: Samuel Zou Date: Thu, 7 May 2020 11:54:07 +0800 Subject: [PATCH 196/428] ALSA: sound/ppc: Use bitwise instead of arithmetic operator for flags Fix the following coccinelle warnings: sound/ppc/pmac.c:729:57-58: WARNING: sum of probable bitmasks, consider | sound/ppc/pmac.c:229:37-38: WARNING: sum of probable bitmasks, consider | Reported-by: Hulk Robot Signed-off-by: Samuel Zou Link: https://lore.kernel.org/r/1588823647-12480-1-git-send-email-zou_wei@huawei.com Signed-off-by: Takashi Iwai --- sound/ppc/pmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 592532c09a82..2e750b317be1 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -226,7 +226,7 @@ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, offset += rec->period_size; } /* make loop */ - cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS); + cp->command = cpu_to_le16(DBDMA_NOP | BR_ALWAYS); cp->cmd_dep = cpu_to_le32(rec->cmd.addr); snd_pmac_dma_stop(rec); @@ -726,7 +726,7 @@ void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long add chip->extra_dma.cmds->xfer_status = cpu_to_le16(0); chip->extra_dma.cmds->cmd_dep = cpu_to_le32(chip->extra_dma.addr); chip->extra_dma.cmds->phy_addr = cpu_to_le32(addr); - chip->extra_dma.cmds->command = cpu_to_le16(OUTPUT_MORE + BR_ALWAYS); + chip->extra_dma.cmds->command = cpu_to_le16(OUTPUT_MORE | BR_ALWAYS); out_le32(&chip->awacs->control, (in_le32(&chip->awacs->control) & ~0x1f00) | (speed << 8)); From 28a04aa3ba6046028036d68eab6b9f3f91b47e4e Mon Sep 17 00:00:00 2001 From: Samuel Zou Date: Thu, 7 May 2020 14:48:55 +0800 Subject: [PATCH 197/428] ALSA: portman2x4: Use bitwise instead of arithmetic operator for flags Fix the following coccinelle warning: sound/drivers/portman2x4.c:460:34-35: WARNING: sum of probable bitmasks, consider | Reported-by: Hulk Robot Signed-off-by: Samuel Zou Link: https://lore.kernel.org/r/1588834135-14842-1-git-send-email-zou_wei@huawei.com Signed-off-by: Takashi Iwai --- sound/drivers/portman2x4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index ecefa7c83134..38603cb2bd5b 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -457,7 +457,7 @@ static int portman_probe(struct parport *p) /* Set for RXDATA0 where no damage will be done. */ /* 5 */ - parport_write_control(p, RXDATA0 + STROBE); /* Write Strobe=1 to command reg. */ + parport_write_control(p, RXDATA0 | STROBE); /* Write Strobe=1 to command reg. */ /* 6 */ if ((parport_read_status(p) & ESTB) != ESTB) From df1fceacb24853d79f41a1dd717b32ab08fa5f3f Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 6 May 2020 22:39:51 +0200 Subject: [PATCH 198/428] ALSA: hda: Allow SST driver on SKL and KBL platforms with DMIC Update intel-dspcfg with FLAG_SST_ONLY_IF_DMIC option and use it for Skylake and Kabylake platforms when DMIC is present. Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200506203951.6369-1-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/hda/intel-dsp-config.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index 1c1fdab2a55f..20b8f6cb3ff8 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -19,6 +19,7 @@ MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=lega #define FLAG_SST BIT(0) #define FLAG_SOF BIT(1) +#define FLAG_SST_ONLY_IF_DMIC BIT(15) #define FLAG_SOF_ONLY_IF_DMIC BIT(16) #define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17) @@ -107,6 +108,10 @@ static const struct config_entry config_table[] = { {} } }, + { + .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, + .device = 0x9d70, + }, #endif /* Kabylake-LP */ #if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) @@ -123,6 +128,10 @@ static const struct config_entry config_table[] = { {} } }, + { + .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, + .device = 0x9d71, + }, #endif /* @@ -410,8 +419,17 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) return SND_INTEL_DSP_DRIVER_SOF; } - if (cfg->flags & FLAG_SST) - return SND_INTEL_DSP_DRIVER_SST; + + if (cfg->flags & FLAG_SST) { + if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { + if (snd_intel_dsp_check_dmic(pci)) { + dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); + return SND_INTEL_DSP_DRIVER_SST; + } + } else { + return SND_INTEL_DSP_DRIVER_SST; + } + } return SND_INTEL_DSP_DRIVER_LEGACY; } From fe944625194515e99fcbfb0d190d50986e2b6480 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 7 May 2020 09:54:42 +0800 Subject: [PATCH 199/428] ASoC: mediatek: mt8183: fix error handling of platform_get_irq() platform_get_irq() returns negative value on error instead of 0. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200507015442.191336-1-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index c8ded53bde1d..e0c4714da92c 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -1186,10 +1186,9 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) /* request irq */ irq_id = platform_get_irq(pdev, 0); - if (!irq_id) { - dev_err(dev, "%pOFn no irq found\n", dev->of_node); - return -ENXIO; - } + if (irq_id < 0) + return irq_id; + ret = devm_request_irq(dev, irq_id, mt8183_afe_irq_handler, IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); if (ret) { From 9558ad215509b75c72c84f4f7691f1bd80fda42a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 7 May 2020 09:43:35 +0000 Subject: [PATCH 200/428] ASoC: rt5677: Use devm_snd_soc_register_component() Using devm_snd_soc_register_component() can make the code shorter and cleaner. Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20200507094335.14302-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677-spi.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index 3f40d2751833..7bfade8b3d6e 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c @@ -605,20 +605,15 @@ static int rt5677_spi_probe(struct spi_device *spi) g_spi = spi; - ret = snd_soc_register_component(&spi->dev, &rt5677_spi_dai_component, - &rt5677_spi_dai, 1); + ret = devm_snd_soc_register_component(&spi->dev, + &rt5677_spi_dai_component, + &rt5677_spi_dai, 1); if (ret < 0) dev_err(&spi->dev, "Failed to register component.\n"); return ret; } -static int rt5677_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_component(&spi->dev); - return 0; -} - static const struct acpi_device_id rt5677_spi_acpi_id[] = { { "RT5677AA", 0 }, { } @@ -631,7 +626,6 @@ static struct spi_driver rt5677_spi_driver = { .acpi_match_table = ACPI_PTR(rt5677_spi_acpi_id), }, .probe = rt5677_spi_probe, - .remove = rt5677_spi_remove, }; module_spi_driver(rt5677_spi_driver); From 79a4b670b4b4dddfdb2e946139a88306e3b2ca09 Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Thu, 7 May 2020 10:15:38 +0800 Subject: [PATCH 201/428] ASoC: rt1016: Add the rt1016 support The patch adds the rt1016 support. Signed-off-by: Oder Chiou Link: https://lore.kernel.org/r/20200507021539.7133-1-oder_chiou@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1016.c | 695 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/rt1016.h | 232 +++++++++++++ 2 files changed, 927 insertions(+) create mode 100644 sound/soc/codecs/rt1016.c create mode 100644 sound/soc/codecs/rt1016.h diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c new file mode 100644 index 000000000000..a23d368ab4da --- /dev/null +++ b/sound/soc/codecs/rt1016.c @@ -0,0 +1,695 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// rt1016.c -- RT1016 ALSA SoC audio amplifier driver +// +// Copyright 2020 Realtek Semiconductor Corp. +// Author: Oder Chiou +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rl6231.h" +#include "rt1016.h" + +static const struct reg_sequence rt1016_patch[] = { + {RT1016_VOL_CTRL_3, 0x8900}, + {RT1016_ANA_CTRL_1, 0xa002}, + {RT1016_ANA_CTRL_2, 0x0002}, + {RT1016_CLOCK_4, 0x6700}, + {RT1016_CLASSD_3, 0xdc55}, + {RT1016_CLASSD_4, 0x376a}, + {RT1016_CLASSD_5, 0x009f}, +}; + +static const struct reg_default rt1016_reg[] = { + {0x00, 0x0000}, + {0x01, 0x5400}, + {0x02, 0x5506}, + {0x03, 0xf800}, + {0x04, 0x0000}, + {0x05, 0xbfbf}, + {0x06, 0x8900}, + {0x07, 0xa002}, + {0x08, 0x0000}, + {0x09, 0x0000}, + {0x0a, 0x0000}, + {0x0c, 0x0000}, + {0x0d, 0x0000}, + {0x0e, 0x10ec}, + {0x0f, 0x6595}, + {0x11, 0x0002}, + {0x1c, 0x0000}, + {0x1d, 0x0000}, + {0x1e, 0x0000}, + {0x1f, 0xf000}, + {0x20, 0x0000}, + {0x21, 0x6000}, + {0x22, 0x0000}, + {0x23, 0x6700}, + {0x24, 0x0000}, + {0x25, 0x0000}, + {0x26, 0x0000}, + {0x40, 0x0018}, + {0x60, 0x00a5}, + {0x80, 0x0010}, + {0x81, 0x0009}, + {0x82, 0x0000}, + {0x83, 0x0000}, + {0xa0, 0x0700}, + {0xc0, 0x0080}, + {0xc1, 0x02a0}, + {0xc2, 0x1400}, + {0xc3, 0x0a4a}, + {0xc4, 0x552a}, + {0xc5, 0x087e}, + {0xc6, 0x0020}, + {0xc7, 0xa833}, + {0xc8, 0x0433}, + {0xc9, 0x8040}, + {0xca, 0xdc55}, + {0xcb, 0x376a}, + {0xcc, 0x009f}, + {0xcf, 0x0020}, +}; + +static bool rt1016_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT1016_ANA_FLAG: + case RT1016_VERSION2_ID: + case RT1016_VERSION1_ID: + case RT1016_VENDER_ID: + case RT1016_DEVICE_ID: + case RT1016_TEST_SIGNAL: + case RT1016_SC_CTRL_1: + return true; + + default: + return false; + } +} + +static bool rt1016_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT1016_RESET: + case RT1016_PADS_CTRL_1: + case RT1016_PADS_CTRL_2: + case RT1016_I2C_CTRL: + case RT1016_VOL_CTRL_1: + case RT1016_VOL_CTRL_2: + case RT1016_VOL_CTRL_3: + case RT1016_ANA_CTRL_1: + case RT1016_MUX_SEL: + case RT1016_RX_I2S_CTRL: + case RT1016_ANA_FLAG: + case RT1016_VERSION2_ID: + case RT1016_VERSION1_ID: + case RT1016_VENDER_ID: + case RT1016_DEVICE_ID: + case RT1016_ANA_CTRL_2: + case RT1016_TEST_SIGNAL: + case RT1016_TEST_CTRL_1: + case RT1016_TEST_CTRL_2: + case RT1016_TEST_CTRL_3: + case RT1016_CLOCK_1: + case RT1016_CLOCK_2: + case RT1016_CLOCK_3: + case RT1016_CLOCK_4: + case RT1016_CLOCK_5: + case RT1016_CLOCK_6: + case RT1016_CLOCK_7: + case RT1016_I2S_CTRL: + case RT1016_DAC_CTRL_1: + case RT1016_SC_CTRL_1: + case RT1016_SC_CTRL_2: + case RT1016_SC_CTRL_3: + case RT1016_SC_CTRL_4: + case RT1016_SIL_DET: + case RT1016_SYS_CLK: + case RT1016_BIAS_CUR: + case RT1016_DAC_CTRL_2: + case RT1016_LDO_CTRL: + case RT1016_CLASSD_1: + case RT1016_PLL1: + case RT1016_PLL2: + case RT1016_PLL3: + case RT1016_CLASSD_2: + case RT1016_CLASSD_OUT: + case RT1016_CLASSD_3: + case RT1016_CLASSD_4: + case RT1016_CLASSD_5: + case RT1016_PWR_CTRL: + return true; + + default: + return false; + } +} + +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9550, 50, 0); + +static const struct snd_kcontrol_new rt1016_snd_controls[] = { + SOC_DOUBLE_TLV("DAC Playback Volume", RT1016_VOL_CTRL_2, + RT1016_L_VOL_SFT, RT1016_R_VOL_SFT, 191, 0, dac_vol_tlv), + SOC_DOUBLE("DAC Playback Switch", RT1016_VOL_CTRL_1, + RT1016_DA_MUTE_L_SFT, RT1016_DA_MUTE_R_SFT, 1, 1), +}; + +static int rt1016_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 rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); + + if (rt1016->sysclk_src == RT1016_SCLK_S_PLL) + return 1; + else + return 0; +} + +/* Interface data select */ +static const char * const rt1016_data_select[] = { + "L/R", "R/L", "L/L", "R/R" +}; + +static SOC_ENUM_SINGLE_DECL(rt1016_if_data_swap_enum, + RT1016_I2S_CTRL, RT1016_I2S_DATA_SWAP_SFT, rt1016_data_select); + +static const struct snd_kcontrol_new rt1016_if_data_swap_mux = + SOC_DAPM_ENUM("Data Swap Mux", rt1016_if_data_swap_enum); + +static const struct snd_soc_dapm_widget rt1016_dapm_widgets[] = { + SND_SOC_DAPM_MUX("Data Swap Mux", SND_SOC_NOPM, 0, 0, + &rt1016_if_data_swap_mux), + + SND_SOC_DAPM_SUPPLY("DAC Filter", RT1016_CLOCK_3, + RT1016_PWR_DAC_FILTER_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAMOD", RT1016_CLOCK_3, RT1016_PWR_DACMOD_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("FIFO", RT1016_CLOCK_3, RT1016_PWR_CLK_FIFO_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("Pure DC", RT1016_CLOCK_3, + RT1016_PWR_CLK_PUREDC_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CLK Silence Det", RT1016_CLOCK_3, + RT1016_PWR_SIL_DET_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("RC 25M", RT1016_CLOCK_3, RT1016_PWR_RC_25M_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL1", RT1016_CLOCK_3, RT1016_PWR_PLL1_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("ANA CTRL", RT1016_CLOCK_3, RT1016_PWR_ANA_CTRL_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CLK SYS", RT1016_CLOCK_3, RT1016_PWR_CLK_SYS_BIT, + 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("LRCK Det", RT1016_CLOCK_4, RT1016_PWR_LRCK_DET_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BCLK Det", RT1016_CLOCK_4, RT1016_PWR_BCLK_DET_BIT, + 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("CKGEN DAC", RT1016_DAC_CTRL_2, + RT1016_CKGEN_DAC_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("VCM SLOW", RT1016_CLASSD_1, RT1016_VCM_SLOW_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("Silence Det", RT1016_SIL_DET, + RT1016_SIL_DET_EN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL2", RT1016_PLL2, RT1016_PLL2_EN_BIT, 0, NULL, + 0), + + SND_SOC_DAPM_SUPPLY_S("BG1 BG2", 1, RT1016_PWR_CTRL, + RT1016_PWR_BG_1_2_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("MBIAS BG", 1, RT1016_PWR_CTRL, + RT1016_PWR_MBIAS_BG_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("PLL", 1, RT1016_PWR_CTRL, RT1016_PWR_PLL_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("BASIC", 1, RT1016_PWR_CTRL, RT1016_PWR_BASIC_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("CLASS D", 1, RT1016_PWR_CTRL, + RT1016_PWR_CLSD_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("25M", 1, RT1016_PWR_CTRL, RT1016_PWR_25M_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DACL", 1, RT1016_PWR_CTRL, RT1016_PWR_DACL_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DACR", 1, RT1016_PWR_CTRL, RT1016_PWR_DACR_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("LDO2", 1, RT1016_PWR_CTRL, RT1016_PWR_LDO2_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("VREF", 1, RT1016_PWR_CTRL, RT1016_PWR_VREF_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("MBIAS", 1, RT1016_PWR_CTRL, RT1016_PWR_MBIAS_BIT, + 0, NULL, 0), + + SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_OUTPUT("SPO"), +}; + +static const struct snd_soc_dapm_route rt1016_dapm_routes[] = { + { "Data Swap Mux", "L/R", "AIFRX" }, + { "Data Swap Mux", "R/L", "AIFRX" }, + { "Data Swap Mux", "L/L", "AIFRX" }, + { "Data Swap Mux", "R/R", "AIFRX" }, + + { "DAC", NULL, "DAC Filter" }, + { "DAC", NULL, "DAMOD" }, + { "DAC", NULL, "FIFO" }, + { "DAC", NULL, "Pure DC" }, + { "DAC", NULL, "Silence Det" }, + { "DAC", NULL, "ANA CTRL" }, + { "DAC", NULL, "CLK SYS" }, + { "DAC", NULL, "LRCK Det" }, + { "DAC", NULL, "BCLK Det" }, + { "DAC", NULL, "CKGEN DAC" }, + { "DAC", NULL, "VCM SLOW" }, + + { "PLL", NULL, "PLL1" }, + { "PLL", NULL, "PLL2" }, + { "25M", NULL, "RC 25M" }, + { "Silence Det", NULL, "CLK Silence Det" }, + + { "DAC", NULL, "Data Swap Mux" }, + { "DAC", NULL, "BG1 BG2" }, + { "DAC", NULL, "MBIAS BG" }, + { "DAC", NULL, "PLL", rt1016_is_sys_clk_from_pll}, + { "DAC", NULL, "BASIC" }, + { "DAC", NULL, "CLASS D" }, + { "DAC", NULL, "25M" }, + { "DAC", NULL, "DACL" }, + { "DAC", NULL, "DACR" }, + { "DAC", NULL, "LDO2" }, + { "DAC", NULL, "VREF" }, + { "DAC", NULL, "MBIAS" }, + + { "SPO", NULL, "DAC" }, +}; + +static int rt1016_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 rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); + int pre_div, bclk_ms, frame_size; + unsigned int val_len = 0; + + rt1016->lrck = params_rate(params); + pre_div = rl6231_get_clk_info(rt1016->sysclk, rt1016->lrck); + if (pre_div < 0) { + dev_err(component->dev, "Unsupported clock rate\n"); + 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; + rt1016->bclk = rt1016->lrck * (32 << bclk_ms); + + if (bclk_ms && rt1016->master) + snd_soc_component_update_bits(component, RT1016_I2S_CTRL, + RT1016_I2S_BCLK_MS_MASK, RT1016_I2S_BCLK_MS_64); + + dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n", + rt1016->lrck, pre_div, dai->id); + + switch (params_width(params)) { + case 16: + val_len = RT1016_I2S_DL_16; + break; + case 20: + val_len = RT1016_I2S_DL_20; + break; + case 24: + val_len = RT1016_I2S_DL_24; + break; + case 32: + val_len = RT1016_I2S_DL_32; + break; + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, RT1016_I2S_CTRL, + RT1016_I2S_DL_MASK, val_len); + snd_soc_component_update_bits(component, RT1016_CLOCK_2, + RT1016_FS_PD_MASK | RT1016_OSR_PD_MASK, + ((pre_div + 3) << RT1016_FS_PD_SFT) | + (pre_div << RT1016_OSR_PD_SFT)); + + return 0; +} + +static int rt1016_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); + unsigned int reg_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + reg_val |= RT1016_I2S_MS_M; + rt1016->master = 1; + break; + case SND_SOC_DAIFMT_CBS_CFS: + reg_val |= RT1016_I2S_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_val |= RT1016_I2S_BCLK_POL_INV; + 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 |= RT1016_I2S_DF_LEFT; + break; + + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT1016_I2S_DF_PCM_A; + break; + + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT1016_I2S_DF_PCM_B; + break; + + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, RT1016_I2S_CTRL, + RT1016_I2S_MS_MASK | RT1016_I2S_BCLK_POL_MASK | + RT1016_I2S_DF_MASK, reg_val); + + return 0; +} + +static int rt1016_set_component_sysclk(struct snd_soc_component *component, + int clk_id, int source, unsigned int freq, int dir) +{ + struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); + unsigned int reg_val = 0; + + if (freq == rt1016->sysclk && clk_id == rt1016->sysclk_src) + return 0; + + switch (clk_id) { + case RT1016_SCLK_S_MCLK: + reg_val |= RT1016_CLK_SYS_SEL_MCLK; + break; + + case RT1016_SCLK_S_PLL: + reg_val |= RT1016_CLK_SYS_SEL_PLL; + break; + + default: + dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + + rt1016->sysclk = freq; + rt1016->sysclk_src = clk_id; + + dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n", + freq, clk_id); + + snd_soc_component_update_bits(component, RT1016_CLOCK_1, + RT1016_CLK_SYS_SEL_MASK, reg_val); + + return 0; +} + +static int rt1016_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, unsigned int freq_in, + unsigned int freq_out) +{ + struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); + struct rl6231_pll_code pll_code; + int ret; + + if (!freq_in || !freq_out) { + dev_dbg(component->dev, "PLL disabled\n"); + + rt1016->pll_in = 0; + rt1016->pll_out = 0; + + return 0; + } + + if (source == rt1016->pll_src && freq_in == rt1016->pll_in && + freq_out == rt1016->pll_out) + return 0; + + switch (source) { + case RT1016_PLL_S_MCLK: + snd_soc_component_update_bits(component, RT1016_CLOCK_1, + RT1016_PLL_SEL_MASK, RT1016_PLL_SEL_MCLK); + break; + + case RT1016_PLL_S_BCLK: + snd_soc_component_update_bits(component, RT1016_CLOCK_1, + RT1016_PLL_SEL_MASK, RT1016_PLL_SEL_BCLK); + break; + + default: + dev_err(component->dev, "Unknown PLL Source %d\n", source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out * 4, &pll_code); + if (ret < 0) { + dev_err(component->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(component->dev, "mbypass=%d m=%d n=%d kbypass=%d k=%d\n", + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), + pll_code.n_code, pll_code.k_bp, + (pll_code.k_bp ? 0 : pll_code.k_code)); + + snd_soc_component_write(component, RT1016_PLL1, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT1016_PLL_M_SFT | + pll_code.m_bp << RT1016_PLL_M_BP_SFT | pll_code.n_code); + snd_soc_component_write(component, RT1016_PLL2, + pll_code.k_bp << RT1016_PLL_K_BP_SFT | + (pll_code.k_bp ? 0 : pll_code.k_code)); + + rt1016->pll_in = freq_in; + rt1016->pll_out = freq_out; + rt1016->pll_src = source; + + return 0; +} + +static int rt1016_probe(struct snd_soc_component *component) +{ + struct rt1016_priv *rt1016 = + snd_soc_component_get_drvdata(component); + + rt1016->component = component; + + return 0; +} + +static void rt1016_remove(struct snd_soc_component *component) +{ + struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); + + regmap_write(rt1016->regmap, RT1016_RESET, 0); +} + +#define RT1016_STEREO_RATES SNDRV_PCM_RATE_8000_48000 +#define RT1016_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) + +static struct snd_soc_dai_ops rt1016_aif_dai_ops = { + .hw_params = rt1016_hw_params, + .set_fmt = rt1016_set_dai_fmt, +}; + +static struct snd_soc_dai_driver rt1016_dai[] = { + { + .name = "rt1016-aif", + .id = 0, + .playback = { + .stream_name = "AIF Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT1016_STEREO_RATES, + .formats = RT1016_FORMATS, + }, + .ops = &rt1016_aif_dai_ops, + } +}; + +#ifdef CONFIG_PM +static int rt1016_suspend(struct snd_soc_component *component) +{ + struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt1016->regmap, true); + regcache_mark_dirty(rt1016->regmap); + + return 0; +} + +static int rt1016_resume(struct snd_soc_component *component) +{ + struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt1016->regmap, false); + regcache_sync(rt1016->regmap); + + return 0; +} +#else +#define rt1016_suspend NULL +#define rt1016_resume NULL +#endif + +static const struct snd_soc_component_driver soc_component_dev_rt1016 = { + .probe = rt1016_probe, + .remove = rt1016_remove, + .suspend = rt1016_suspend, + .resume = rt1016_resume, + .controls = rt1016_snd_controls, + .num_controls = ARRAY_SIZE(rt1016_snd_controls), + .dapm_widgets = rt1016_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt1016_dapm_widgets), + .dapm_routes = rt1016_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt1016_dapm_routes), + .set_sysclk = rt1016_set_component_sysclk, + .set_pll = rt1016_set_component_pll, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct regmap_config rt1016_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = RT1016_PWR_CTRL, + .volatile_reg = rt1016_volatile_register, + .readable_reg = rt1016_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt1016_reg, + .num_reg_defaults = ARRAY_SIZE(rt1016_reg), +}; + +static const struct i2c_device_id rt1016_i2c_id[] = { + { "rt1016", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt1016_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id rt1016_of_match[] = { + { .compatible = "realtek,rt1016", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt1016_of_match); +#endif + +#ifdef CONFIG_ACPI +static struct acpi_device_id rt1016_acpi_match[] = { + {"10EC1016", 0,}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, rt1016_acpi_match); +#endif + +static int rt1016_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt1016_priv *rt1016; + int ret; + unsigned int val; + + rt1016 = devm_kzalloc(&i2c->dev, sizeof(struct rt1016_priv), + GFP_KERNEL); + if (rt1016 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt1016); + + rt1016->regmap = devm_regmap_init_i2c(i2c, &rt1016_regmap); + if (IS_ERR(rt1016->regmap)) { + ret = PTR_ERR(rt1016->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + regmap_read(rt1016->regmap, RT1016_DEVICE_ID, &val); + if (val != RT1016_DEVICE_ID_VAL) { + dev_err(&i2c->dev, + "Device with ID register %x is not rt1016\n", val); + return -ENODEV; + } + + regmap_write(rt1016->regmap, RT1016_RESET, 0); + + ret = regmap_register_patch(rt1016->regmap, rt1016_patch, + ARRAY_SIZE(rt1016_patch)); + if (ret != 0) + dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); + + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_rt1016, + rt1016_dai, ARRAY_SIZE(rt1016_dai)); +} + +static void rt1016_i2c_shutdown(struct i2c_client *client) +{ + struct rt1016_priv *rt1016 = i2c_get_clientdata(client); + + regmap_write(rt1016->regmap, RT1016_RESET, 0); +} + +static struct i2c_driver rt1016_i2c_driver = { + .driver = { + .name = "rt1016", + .of_match_table = of_match_ptr(rt1016_of_match), + .acpi_match_table = ACPI_PTR(rt1016_acpi_match), + }, + .probe = rt1016_i2c_probe, + .shutdown = rt1016_i2c_shutdown, + .id_table = rt1016_i2c_id, +}; +module_i2c_driver(rt1016_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT1016 driver"); +MODULE_AUTHOR("Oder Chiou "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt1016.h b/sound/soc/codecs/rt1016.h new file mode 100644 index 000000000000..041d6a5a6f46 --- /dev/null +++ b/sound/soc/codecs/rt1016.h @@ -0,0 +1,232 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * rt1016.h -- RT1016 ALSA SoC audio amplifier driver + * + * Copyright 2020 Realtek Semiconductor Corp. + * Author: Oder Chiou + * + * 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 __RT1016_H__ +#define __RT1016_H__ + +#define RT1016_DEVICE_ID_VAL 0x6595 + +#define RT1016_RESET 0x00 +#define RT1016_PADS_CTRL_1 0x01 +#define RT1016_PADS_CTRL_2 0x02 +#define RT1016_I2C_CTRL 0x03 +#define RT1016_VOL_CTRL_1 0x04 +#define RT1016_VOL_CTRL_2 0x05 +#define RT1016_VOL_CTRL_3 0x06 +#define RT1016_ANA_CTRL_1 0x07 +#define RT1016_MUX_SEL 0x08 +#define RT1016_RX_I2S_CTRL 0x09 +#define RT1016_ANA_FLAG 0x0a +#define RT1016_VERSION2_ID 0x0c +#define RT1016_VERSION1_ID 0x0d +#define RT1016_VENDER_ID 0x0e +#define RT1016_DEVICE_ID 0x0f +#define RT1016_ANA_CTRL_2 0x11 +#define RT1016_TEST_SIGNAL 0x1c +#define RT1016_TEST_CTRL_1 0x1d +#define RT1016_TEST_CTRL_2 0x1e +#define RT1016_TEST_CTRL_3 0x1f +#define RT1016_CLOCK_1 0x20 +#define RT1016_CLOCK_2 0x21 +#define RT1016_CLOCK_3 0x22 +#define RT1016_CLOCK_4 0x23 +#define RT1016_CLOCK_5 0x24 +#define RT1016_CLOCK_6 0x25 +#define RT1016_CLOCK_7 0x26 +#define RT1016_I2S_CTRL 0x40 +#define RT1016_DAC_CTRL_1 0x60 +#define RT1016_SC_CTRL_1 0x80 +#define RT1016_SC_CTRL_2 0x81 +#define RT1016_SC_CTRL_3 0x82 +#define RT1016_SC_CTRL_4 0x83 +#define RT1016_SIL_DET 0xa0 +#define RT1016_SYS_CLK 0xc0 +#define RT1016_BIAS_CUR 0xc1 +#define RT1016_DAC_CTRL_2 0xc2 +#define RT1016_LDO_CTRL 0xc3 +#define RT1016_CLASSD_1 0xc4 +#define RT1016_PLL1 0xc5 +#define RT1016_PLL2 0xc6 +#define RT1016_PLL3 0xc7 +#define RT1016_CLASSD_2 0xc8 +#define RT1016_CLASSD_OUT 0xc9 +#define RT1016_CLASSD_3 0xca +#define RT1016_CLASSD_4 0xcb +#define RT1016_CLASSD_5 0xcc +#define RT1016_PWR_CTRL 0xcf + +/* global definition */ +#define RT1016_L_VOL_MASK (0xff << 8) +#define RT1016_L_VOL_SFT 8 +#define RT1016_R_VOL_MASK (0xff) +#define RT1016_R_VOL_SFT 0 + +/* 0x04 */ +#define RT1016_DA_MUTE_L_SFT 7 +#define RT1016_DA_MUTE_R_SFT 6 + +/* 0x20 */ +#define RT1016_CLK_SYS_SEL_MASK (0x1 << 15) +#define RT1016_CLK_SYS_SEL_SFT 15 +#define RT1016_CLK_SYS_SEL_MCLK (0x0 << 15) +#define RT1016_CLK_SYS_SEL_PLL (0x1 << 15) +#define RT1016_PLL_SEL_MASK (0x1 << 13) +#define RT1016_PLL_SEL_SFT 13 +#define RT1016_PLL_SEL_MCLK (0x0 << 13) +#define RT1016_PLL_SEL_BCLK (0x1 << 13) + +/* 0x21 */ +#define RT1016_FS_PD_MASK (0x7 << 13) +#define RT1016_FS_PD_SFT 13 +#define RT1016_OSR_PD_MASK (0x3 << 10) +#define RT1016_OSR_PD_SFT 10 + +/* 0x22 */ +#define RT1016_PWR_DAC_FILTER (0x1 << 11) +#define RT1016_PWR_DAC_FILTER_BIT 11 +#define RT1016_PWR_DACMOD (0x1 << 10) +#define RT1016_PWR_DACMOD_BIT 10 +#define RT1016_PWR_CLK_FIFO (0x1 << 9) +#define RT1016_PWR_CLK_FIFO_BIT 9 +#define RT1016_PWR_CLK_PUREDC (0x1 << 8) +#define RT1016_PWR_CLK_PUREDC_BIT 8 +#define RT1016_PWR_SIL_DET (0x1 << 7) +#define RT1016_PWR_SIL_DET_BIT 7 +#define RT1016_PWR_RC_25M (0x1 << 6) +#define RT1016_PWR_RC_25M_BIT 6 +#define RT1016_PWR_PLL1 (0x1 << 5) +#define RT1016_PWR_PLL1_BIT 5 +#define RT1016_PWR_ANA_CTRL (0x1 << 4) +#define RT1016_PWR_ANA_CTRL_BIT 4 +#define RT1016_PWR_CLK_SYS (0x1 << 3) +#define RT1016_PWR_CLK_SYS_BIT 3 + +/* 0x23 */ +#define RT1016_PWR_LRCK_DET (0x1 << 15) +#define RT1016_PWR_LRCK_DET_BIT 15 +#define RT1016_PWR_BCLK_DET (0x1 << 11) +#define RT1016_PWR_BCLK_DET_BIT 11 + +/* 0x40 */ +#define RT1016_I2S_BCLK_MS_MASK (0x1 << 15) +#define RT1016_I2S_BCLK_MS_SFT 15 +#define RT1016_I2S_BCLK_MS_32 (0x0 << 15) +#define RT1016_I2S_BCLK_MS_64 (0x1 << 15) +#define RT1016_I2S_BCLK_POL_MASK (0x1 << 13) +#define RT1016_I2S_BCLK_POL_SFT 13 +#define RT1016_I2S_BCLK_POL_NOR (0x0 << 13) +#define RT1016_I2S_BCLK_POL_INV (0x1 << 13) +#define RT1016_I2S_DATA_SWAP_MASK (0x1 << 10) +#define RT1016_I2S_DATA_SWAP_SFT 10 +#define RT1016_I2S_DL_MASK (0x7 << 4) +#define RT1016_I2S_DL_SFT 4 +#define RT1016_I2S_DL_16 (0x1 << 4) +#define RT1016_I2S_DL_20 (0x2 << 4) +#define RT1016_I2S_DL_24 (0x3 << 4) +#define RT1016_I2S_DL_32 (0x4 << 4) +#define RT1016_I2S_MS_MASK (0x1 << 3) +#define RT1016_I2S_MS_SFT 3 +#define RT1016_I2S_MS_M (0x0 << 3) +#define RT1016_I2S_MS_S (0x1 << 3) +#define RT1016_I2S_DF_MASK (0x7 << 0) +#define RT1016_I2S_DF_SFT 0 +#define RT1016_I2S_DF_I2S (0x0) +#define RT1016_I2S_DF_LEFT (0x1) +#define RT1016_I2S_DF_PCM_A (0x2) +#define RT1016_I2S_DF_PCM_B (0x3) + +/* 0xa0 */ +#define RT1016_SIL_DET_EN (0x1 << 15) +#define RT1016_SIL_DET_EN_BIT 15 + +/* 0xc2 */ +#define RT1016_CKGEN_DAC (0x1 << 13) +#define RT1016_CKGEN_DAC_BIT 13 + +/* 0xc4 */ +#define RT1016_VCM_SLOW (0x1 << 6) +#define RT1016_VCM_SLOW_BIT 6 + +/* 0xc5 */ +#define RT1016_PLL_M_MAX 0xf +#define RT1016_PLL_M_MASK (RT1016_PLL_M_MAX << 12) +#define RT1016_PLL_M_SFT 12 +#define RT1016_PLL_M_BP (0x1 << 11) +#define RT1016_PLL_M_BP_SFT 11 +#define RT1016_PLL_N_MAX 0x1ff +#define RT1016_PLL_N_MASK (RT1016_PLL_N_MAX << 0) +#define RT1016_PLL_N_SFT 0 + +/* 0xc6 */ +#define RT1016_PLL2_EN (0x1 << 15) +#define RT1016_PLL2_EN_BIT 15 +#define RT1016_PLL_K_BP (0x1 << 5) +#define RT1016_PLL_K_BP_SFT 5 +#define RT1016_PLL_K_MAX 0x1f +#define RT1016_PLL_K_MASK (RT1016_PLL_K_MAX) +#define RT1016_PLL_K_SFT 0 + +/* 0xcf */ +#define RT1016_PWR_BG_1_2 (0x1 << 12) +#define RT1016_PWR_BG_1_2_BIT 12 +#define RT1016_PWR_MBIAS_BG (0x1 << 11) +#define RT1016_PWR_MBIAS_BG_BIT 11 +#define RT1016_PWR_PLL (0x1 << 9) +#define RT1016_PWR_PLL_BIT 9 +#define RT1016_PWR_BASIC (0x1 << 8) +#define RT1016_PWR_BASIC_BIT 8 +#define RT1016_PWR_CLSD (0x1 << 7) +#define RT1016_PWR_CLSD_BIT 7 +#define RT1016_PWR_25M (0x1 << 6) +#define RT1016_PWR_25M_BIT 6 +#define RT1016_PWR_DACL (0x1 << 4) +#define RT1016_PWR_DACL_BIT 4 +#define RT1016_PWR_DACR (0x1 << 3) +#define RT1016_PWR_DACR_BIT 3 +#define RT1016_PWR_LDO2 (0x1 << 2) +#define RT1016_PWR_LDO2_BIT 2 +#define RT1016_PWR_VREF (0x1 << 1) +#define RT1016_PWR_VREF_BIT 1 +#define RT1016_PWR_MBIAS (0x1 << 0) +#define RT1016_PWR_MBIAS_BIT 0 + +/* System Clock Source */ +enum { + RT1016_SCLK_S_MCLK, + RT1016_SCLK_S_PLL, +}; + +/* PLL1 Source */ +enum { + RT1016_PLL_S_MCLK, + RT1016_PLL_S_BCLK, +}; + +enum { + RT1016_AIF1, + RT1016_AIFS, +}; + +struct rt1016_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; +}; + +#endif /* __RT1016_H__ */ From 7ae07308e40cb008ef3cc930a02450183a024b9f Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Thu, 7 May 2020 10:15:39 +0800 Subject: [PATCH 202/428] ASoC: rt1016: Add the devicetree file for the rt1016 The patch adds the devicetree file for the rt1016. Signed-off-by: Oder Chiou Link: https://lore.kernel.org/r/20200507021539.7133-2-oder_chiou@realtek.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/rt1016.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/rt1016.txt diff --git a/Documentation/devicetree/bindings/sound/rt1016.txt b/Documentation/devicetree/bindings/sound/rt1016.txt new file mode 100644 index 000000000000..2310f8ff259b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt1016.txt @@ -0,0 +1,17 @@ +RT1016 Stereo Class D Audio Amplifier + +This device supports I2C only. + +Required properties: + +- compatible : "realtek,rt1016". + +- reg : The I2C address of the device. + + +Example: + +rt1016: codec@1a { + compatible = "realtek,rt1016"; + reg = <0x1a>; +}; From c16e923dd635d383026a306acea540b8e0706c88 Mon Sep 17 00:00:00 2001 From: ChenTao Date: Thu, 7 May 2020 10:29:59 +0800 Subject: [PATCH 203/428] soc: fsl_asrc: Make some functions static Fix the following warning: sound/soc/fsl/fsl_asrc.c:157:5: warning: symbol 'fsl_asrc_request_pair' was not declared. Should it be static? sound/soc/fsl/fsl_asrc.c:200:6: warning: symbol 'fsl_asrc_release_pair' was not declared. Should it be static? Reported-by: Hulk Robot Signed-off-by: ChenTao Link: https://lore.kernel.org/r/20200507022959.183739-1-chentao107@huawei.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 067a54ab554f..432936039de4 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -154,7 +154,7 @@ static void fsl_asrc_sel_proc(int inrate, int outrate, * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A * while pair A and pair C are comparatively independent. */ -int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) +static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) { enum asrc_pair_index index = ASRC_INVALID_PAIR; struct fsl_asrc *asrc = pair->asrc; @@ -197,7 +197,7 @@ int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) * * It clears the resource from asrc and releases the occupied channels. */ -void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) +static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) { struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; From 9ad06ebb9ad6ec4bb707f2a4a352ad6c382b5cd5 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 May 2020 14:22:23 -0500 Subject: [PATCH 204/428] ALSA: Replace zero-length array with flexible-array The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] sizeof(flexible-array-member) triggers a warning because flexible array members have incomplete type[1]. There are some instances of code in which the sizeof operator is being incorrectly/erroneously applied to zero-length arrays and the result is zero. Such instances may be hiding some bugs. So, this work (flexible-array member conversions) will also help to get completely rid of those sorts of issues. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200507192223.GA16335@embeddedor Signed-off-by: Takashi Iwai --- include/sound/control.h | 2 +- include/sound/intel-nhlt.h | 6 +++--- sound/core/oss/pcm_plugin.h | 2 +- sound/usb/usx2y/usbusx2y.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/sound/control.h b/include/sound/control.h index 11feeee31e35..aeaed2a05bae 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -75,7 +75,7 @@ struct snd_kcontrol { unsigned long private_value; void *private_data; void (*private_free)(struct snd_kcontrol *kcontrol); - struct snd_kcontrol_volatile vd[0]; /* volatile data */ + struct snd_kcontrol_volatile vd[]; /* volatile data */ }; #define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list) diff --git a/include/sound/intel-nhlt.h b/include/sound/intel-nhlt.h index f657fd8fc0ad..743c2f442280 100644 --- a/include/sound/intel-nhlt.h +++ b/include/sound/intel-nhlt.h @@ -50,7 +50,7 @@ enum nhlt_device_type { struct nhlt_specific_cfg { u32 size; - u8 caps[0]; + u8 caps[]; } __packed; struct nhlt_fmt_cfg { @@ -60,7 +60,7 @@ struct nhlt_fmt_cfg { struct nhlt_fmt { u8 fmt_count; - struct nhlt_fmt_cfg fmt_config[0]; + struct nhlt_fmt_cfg fmt_config[]; } __packed; struct nhlt_endpoint { @@ -80,7 +80,7 @@ struct nhlt_endpoint { struct nhlt_acpi_table { struct acpi_table_header header; u8 endpoint_count; - struct nhlt_endpoint desc[0]; + struct nhlt_endpoint desc[]; } __packed; struct nhlt_resource_desc { diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index 8d2f7a4e3ab6..46e273bd4a78 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h @@ -64,7 +64,7 @@ struct snd_pcm_plugin { char *buf; snd_pcm_uframes_t buf_frames; struct snd_pcm_plugin_channel *buf_channels; - char extra_data[0]; + char extra_data[]; }; int snd_pcm_plugin_build(struct snd_pcm_substream *handle, diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h index e0f77172ce8f..144b85f57bd2 100644 --- a/sound/usb/usx2y/usbusx2y.h +++ b/sound/usb/usx2y/usbusx2y.h @@ -18,7 +18,7 @@ struct snd_usX2Y_AsyncSeq { struct snd_usX2Y_urbSeq { int submitted; int len; - struct urb *urb[0]; + struct urb *urb[]; }; #include "usx2yhwdeppcm.h" From 89ebe49aaa2f60a19db53b4c03fd25253ae7f4ec Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 May 2020 13:52:45 -0500 Subject: [PATCH 205/428] ALSA: fireworks: Replace zero-length array with flexible-array The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] sizeof(flexible-array-member) triggers a warning because flexible array members have incomplete type[1]. There are some instances of code in which the sizeof operator is being incorrectly/erroneously applied to zero-length arrays and the result is zero. Such instances may be hiding some bugs. So, this work (flexible-array member conversions) will also help to get completely rid of those sorts of issues. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Acked-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200507185245.GA14270@embeddedor Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index dda797209a27..654e28a6669f 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h @@ -177,7 +177,7 @@ struct snd_efw_phys_meters { u32 in_meters; u32 reserved4; u32 reserved5; - u32 values[0]; + u32 values[]; } __packed; enum snd_efw_clock_source { SND_EFW_CLOCK_SOURCE_INTERNAL = 0, From 8304cf77c92038cd1c50c27b69d30be695cc8003 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:26 +0900 Subject: [PATCH 206/428] ALSA: firewire-lib: fix invalid assignment to union data for directional parameter Although the value of FDF is used just for outgoing stream, the assignment to union member is done for both directions of stream. At present this causes no issue because the value of same position is reassigned later for opposite stream. However, it's better to add if statement. Fixes: d3d10a4a1b19 ("ALSA: firewire-lib: use union for directional parameters") Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-2-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-am824.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index 67d735e9a6a4..fea92e148790 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -82,7 +82,8 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate, if (err < 0) return err; - s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc; + if (s->direction == AMDTP_OUT_STREAM) + s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc; p->pcm_channels = pcm_channels; p->midi_ports = midi_ports; From 10aa8e4acf51b12a2db4ee2baaed67f70fbee9c2 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:27 +0900 Subject: [PATCH 207/428] ALSA: firewire-lib: use macro for maximum value of second in 1394 OHCI isoc descriptor In descriptor of isochronous context in 1394 OHCI, the field of second has 3 bit, thus the maximum value is 8. The value is used for correct cycle calculation. This commit replaces hard-coded value with macro to obsolete magic number. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-3-o-takashi@sakamocchi.jp 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 37d38efb4c87..fcde01b54d11 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -20,6 +20,8 @@ #define CYCLES_PER_SECOND 8000 #define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND) +#define OHCI_MAX_SECOND 8 + /* Always support Linux tracing subsystem. */ #define CREATE_TRACE_POINTS #include "amdtp-stream-trace.h" @@ -680,8 +682,8 @@ static inline u32 compute_cycle_count(__be32 ctx_header_tstamp) static inline u32 increment_cycle_count(u32 cycle, unsigned int addend) { cycle += addend; - if (cycle >= 8 * CYCLES_PER_SECOND) - cycle -= 8 * CYCLES_PER_SECOND; + if (cycle >= OHCI_MAX_SECOND * CYCLES_PER_SECOND) + cycle -= OHCI_MAX_SECOND * CYCLES_PER_SECOND; return cycle; } From 2472cfb3232caf8f68e4d93ae830c569b0bbc25b Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:28 +0900 Subject: [PATCH 208/428] ALSA: firewire-lib: add reference to domain structure from stream structure In current implementation, AMDTP domain structure and AMDTP stream structure has one way of reference from the former to the latter. For future extension, bidirectional reference is needed. This commit adds a member into stream structure to refer to domain structure to which the stream belongs. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-4-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 75 ++++++++++------------------------- sound/firewire/amdtp-stream.h | 3 ++ 2 files changed, 23 insertions(+), 55 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index fcde01b54d11..ce63ff6b7f03 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -793,14 +793,6 @@ static void process_ctx_payloads(struct amdtp_stream *s, update_pcm_pointers(s, pcm, pcm_frames); } -static void amdtp_stream_master_callback(struct fw_iso_context *context, - u32 tstamp, size_t header_length, - void *header, void *private_data); - -static void amdtp_stream_master_first_callback(struct fw_iso_context *context, - u32 tstamp, size_t header_length, - void *header, void *private_data); - static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, void *header, void *private_data) @@ -810,7 +802,6 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, unsigned int events_per_period = s->ctx_data.rx.events_per_period; unsigned int event_count = s->ctx_data.rx.event_count; unsigned int packets; - bool is_irq_target; int i; if (s->packet_index < 0) @@ -823,10 +814,6 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, process_ctx_payloads(s, s->pkt_descs, packets); - is_irq_target = - !!(context->callback.sc == amdtp_stream_master_callback || - context->callback.sc == amdtp_stream_master_first_callback); - for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = s->pkt_descs + i; unsigned int syt; @@ -845,7 +832,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, desc->data_blocks, desc->data_block_counter, syt, i); - if (is_irq_target) { + if (s == s->domain->irq_target) { event_count += desc->data_blocks; if (event_count >= events_per_period) { event_count -= events_per_period; @@ -898,12 +885,12 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, } } -static void amdtp_stream_master_callback(struct fw_iso_context *context, - u32 tstamp, size_t header_length, - void *header, void *private_data) +static void irq_target_callback(struct fw_iso_context *context, u32 tstamp, + size_t header_length, void *header, + void *private_data) { - struct amdtp_domain *d = private_data; - struct amdtp_stream *irq_target = d->irq_target; + struct amdtp_stream *irq_target = private_data; + struct amdtp_domain *d = irq_target->domain; struct amdtp_stream *s; out_stream_callback(context, tstamp, header_length, header, irq_target); @@ -952,7 +939,10 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, } else { cycle = compute_it_cycle(*ctx_header, s->queue_size); - context->callback.sc = out_stream_callback; + if (s == s->domain->irq_target) + context->callback.sc = irq_target_callback; + else + context->callback.sc = out_stream_callback; } s->start_cycle = cycle; @@ -960,32 +950,11 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, context->callback.sc(context, tstamp, header_length, header, s); } -static void amdtp_stream_master_first_callback(struct fw_iso_context *context, - u32 tstamp, size_t header_length, - void *header, void *private_data) -{ - struct amdtp_domain *d = private_data; - struct amdtp_stream *s = d->irq_target; - const __be32 *ctx_header = header; - - s->callbacked = true; - wake_up(&s->callback_wait); - - s->start_cycle = compute_it_cycle(*ctx_header, s->queue_size); - - context->callback.sc = amdtp_stream_master_callback; - - context->callback.sc(context, tstamp, header_length, header, d); -} - /** * amdtp_stream_start - start transferring packets * @s: the AMDTP stream to start * @channel: the isochronous channel on the bus * @speed: firewire speed code - * @d: the AMDTP domain to which the AMDTP stream belongs - * @is_irq_target: whether isoc context for the AMDTP stream is used to generate - * hardware IRQ. * @start_cycle: the isochronous cycle to start the context. Start immediately * if negative value is given. * @@ -994,7 +963,6 @@ static void amdtp_stream_master_first_callback(struct fw_iso_context *context, * device can be started. */ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, - struct amdtp_domain *d, bool is_irq_target, int start_cycle) { static const struct { @@ -1009,15 +977,14 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, [CIP_SFC_88200] = { 0, 67 }, [CIP_SFC_176400] = { 0, 67 }, }; - unsigned int events_per_buffer = d->events_per_buffer; - unsigned int events_per_period = d->events_per_period; + bool is_irq_target = (s == s->domain->irq_target); + unsigned int events_per_buffer; + unsigned int events_per_period; unsigned int idle_irq_interval; unsigned int ctx_header_size; unsigned int max_ctx_payload_size; enum dma_data_direction dir; int type, tag, err; - fw_iso_callback_t ctx_cb; - void *ctx_data; mutex_lock(&s->mutex); @@ -1068,6 +1035,8 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, // This is a case that AMDTP streams in domain run just for MIDI // substream. Use the number of events equivalent to 10 msec as // interval of hardware IRQ. + events_per_buffer = s->domain->events_per_buffer; + events_per_period = s->domain->events_per_period; if (events_per_period == 0) events_per_period = amdtp_rate_table[s->sfc] / 100; if (events_per_buffer == 0) @@ -1086,16 +1055,11 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, if (is_irq_target) { s->ctx_data.rx.events_per_period = events_per_period; s->ctx_data.rx.event_count = 0; - ctx_cb = amdtp_stream_master_first_callback; - ctx_data = d; - } else { - ctx_cb = amdtp_stream_first_callback; - ctx_data = s; } s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, type, channel, speed, ctx_header_size, - ctx_cb, ctx_data); + amdtp_stream_first_callback, s); if (IS_ERR(s->context)) { err = PTR_ERR(s->context); if (err == -EBUSY) @@ -1340,6 +1304,7 @@ int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, s->channel = channel; s->speed = speed; + s->domain = d; return 0; } @@ -1428,15 +1393,15 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) } if (s != d->irq_target) { - err = amdtp_stream_start(s, s->channel, s->speed, d, - false, cycle_match); + err = amdtp_stream_start(s, s->channel, s->speed, + cycle_match); if (err < 0) goto error; } } s = d->irq_target; - err = amdtp_stream_start(s, s->channel, s->speed, d, true, -1); + err = amdtp_stream_start(s, s->channel, s->speed, -1); if (err < 0) goto error; diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index f2d44e2dc3c8..477fbfe713e5 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -108,6 +108,8 @@ typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)( const struct pkt_desc *desc, unsigned int packets, struct snd_pcm_substream *pcm); + +struct amdtp_domain; struct amdtp_stream { struct fw_unit *unit; enum cip_flags flags; @@ -180,6 +182,7 @@ struct amdtp_stream { int channel; int speed; struct list_head list; + struct amdtp_domain *domain; }; int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, From af86b0b1f4b04501fdd12571ffcaae5853ab8a10 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:29 +0900 Subject: [PATCH 209/428] ALSA: firewire-lib: code refactoring for parameters of packet queue and IRQ timing Although the parameter for packet queue and IRQ timing is calculated when AMDTP stream starts, the calculated parameters are the same between streams in AMDTP domain. This commit moves the calculation and decide the parameters when AMDTP domain starts. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-5-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 56 ++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index ce63ff6b7f03..6130c240ff33 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -957,13 +957,16 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, * @speed: firewire speed code * @start_cycle: the isochronous cycle to start the context. Start immediately * if negative value is given. + * @queue_size: The number of packets in the queue. + * @idle_irq_interval: the interval to queue packet during initial state. * * The stream cannot be started until it has been configured with * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI * device can be started. */ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, - int start_cycle) + int start_cycle, unsigned int queue_size, + unsigned int idle_irq_interval) { static const struct { unsigned int data_block; @@ -978,9 +981,6 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, [CIP_SFC_176400] = { 0, 67 }, }; bool is_irq_target = (s == s->domain->irq_target); - unsigned int events_per_buffer; - unsigned int events_per_period; - unsigned int idle_irq_interval; unsigned int ctx_header_size; unsigned int max_ctx_payload_size; enum dma_data_direction dir; @@ -1032,30 +1032,11 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP; } - // This is a case that AMDTP streams in domain run just for MIDI - // substream. Use the number of events equivalent to 10 msec as - // interval of hardware IRQ. - events_per_buffer = s->domain->events_per_buffer; - events_per_period = s->domain->events_per_period; - if (events_per_period == 0) - events_per_period = amdtp_rate_table[s->sfc] / 100; - if (events_per_buffer == 0) - events_per_buffer = events_per_period * 3; - - idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period, - amdtp_rate_table[s->sfc]); - s->queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer, - amdtp_rate_table[s->sfc]); - - err = iso_packets_buffer_init(&s->buffer, s->unit, s->queue_size, + err = iso_packets_buffer_init(&s->buffer, s->unit, queue_size, max_ctx_payload_size, dir); if (err < 0) goto err_unlock; - - if (is_irq_target) { - s->ctx_data.rx.events_per_period = events_per_period; - s->ctx_data.rx.event_count = 0; - } + s->queue_size = queue_size; s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, type, channel, speed, ctx_header_size, @@ -1341,6 +1322,10 @@ static int get_current_cycle_time(struct fw_card *fw_card, int *cur_cycle) */ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) { + unsigned int events_per_buffer = d->events_per_buffer; + unsigned int events_per_period = d->events_per_period; + unsigned int idle_irq_interval; + unsigned int queue_size; struct amdtp_stream *s; int cycle; int err; @@ -1354,6 +1339,17 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) return -ENXIO; d->irq_target = s; + // This is a case that AMDTP streams in domain run just for MIDI + // substream. Use the number of events equivalent to 10 msec as + // interval of hardware IRQ. + if (events_per_period == 0) + events_per_period = amdtp_rate_table[d->irq_target->sfc] / 100; + if (events_per_buffer == 0) + events_per_buffer = events_per_period * 3; + + queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer, + amdtp_rate_table[d->irq_target->sfc]); + if (ir_delay_cycle > 0) { struct fw_card *fw_card = fw_parent_device(s->unit)->card; @@ -1394,14 +1390,20 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) if (s != d->irq_target) { err = amdtp_stream_start(s, s->channel, s->speed, - cycle_match); + cycle_match, queue_size, 0); if (err < 0) goto error; } } s = d->irq_target; - err = amdtp_stream_start(s, s->channel, s->speed, -1); + s->ctx_data.rx.events_per_period = events_per_period; + s->ctx_data.rx.event_count = 0; + + idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period, + amdtp_rate_table[d->irq_target->sfc]); + err = amdtp_stream_start(s, s->channel, s->speed, -1, queue_size, + idle_irq_interval); if (err < 0) goto error; From 83cfb5c50f8e35d795d4260756fb62a2b77ae8df Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:30 +0900 Subject: [PATCH 210/428] ALSA: firewire-lib: code refactoring for syt computation In current implementation for outgoing AMDTP packet, the value of syt field in CIP header is computed when calculating syt offset. For future extension, it's convenient to split the computation and calculation. This commit splits them. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-6-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 36 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 6130c240ff33..1605ea4301ce 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -383,10 +383,9 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s, return data_blocks; } -static unsigned int calculate_syt(struct amdtp_stream *s, - unsigned int cycle) +static unsigned int calculate_syt_offset(struct amdtp_stream *s) { - unsigned int syt_offset, phase, index, syt; + unsigned int syt_offset, phase, index; if (s->ctx_data.rx.last_syt_offset < TICKS_PER_CYCLE) { if (!cip_sfc_is_base_44100(s->sfc)) @@ -416,15 +415,10 @@ static unsigned int calculate_syt(struct amdtp_stream *s, 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->ctx_data.rx.transfer_delay; - syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; - syt += syt_offset % TICKS_PER_CYCLE; + if (syt_offset >= TICKS_PER_CYCLE) + syt_offset = CIP_SYT_NO_INFO; - return syt & CIP_SYT_MASK; - } else { - return CIP_SYT_NO_INFO; - } + return syt_offset; } static void update_pcm_pointers(struct amdtp_stream *s, @@ -740,6 +734,17 @@ static int generate_device_pkt_descs(struct amdtp_stream *s, return 0; } +static unsigned int compute_syt(unsigned int syt_offset, unsigned int cycle, + unsigned int transfer_delay) +{ + unsigned int syt; + + syt_offset += transfer_delay; + syt = ((cycle + syt_offset / TICKS_PER_CYCLE) << 12) | + (syt_offset % TICKS_PER_CYCLE); + return syt & CIP_SYT_MASK; +} + static void generate_ideal_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs, const __be32 *ctx_header, @@ -751,9 +756,16 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s, for (i = 0; i < packets; ++i) { struct pkt_desc *desc = descs + i; unsigned int index = (s->packet_index + i) % s->queue_size; + unsigned int syt_offset; desc->cycle = compute_it_cycle(*ctx_header, s->queue_size); - desc->syt = calculate_syt(s, desc->cycle); + syt_offset = calculate_syt_offset(s); + if (syt_offset != CIP_SYT_NO_INFO) { + desc->syt = compute_syt(syt_offset, desc->cycle, + s->ctx_data.rx.transfer_delay); + } else { + desc->syt = syt_offset; + } desc->data_blocks = calculate_data_blocks(s, desc->syt); if (s->flags & CIP_DBC_IS_END_EVENT) From 816d84826e89399858a1f086d78f5a4dd615a9ae Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:31 +0900 Subject: [PATCH 211/428] ALSA: firewire-lib: code refactoring for syt offset calculation When calculating syt offset, some states are stored in AMDTP stream structure. This is inconvenient when reuse the calculation from non-stream structure. This commit applies refactoring to helper function for the calculation so that the function doesn't touch AMDTP stream structure. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-7-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 1605ea4301ce..9041510cb6aa 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -383,14 +383,14 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s, return data_blocks; } -static unsigned int calculate_syt_offset(struct amdtp_stream *s) +static unsigned int calculate_syt_offset(unsigned int *last_syt_offset, + unsigned int *syt_offset_state, enum cip_sfc sfc) { - unsigned int syt_offset, phase, index; + unsigned int syt_offset; - if (s->ctx_data.rx.last_syt_offset < TICKS_PER_CYCLE) { - if (!cip_sfc_is_base_44100(s->sfc)) - syt_offset = s->ctx_data.rx.last_syt_offset + - s->ctx_data.rx.syt_offset_state; + if (*last_syt_offset < TICKS_PER_CYCLE) { + if (!cip_sfc_is_base_44100(sfc)) + syt_offset = *last_syt_offset + *syt_offset_state; else { /* * The time, in ticks, of the n'th SYT_INTERVAL sample is: @@ -402,18 +402,19 @@ static unsigned int calculate_syt_offset(struct amdtp_stream *s) * 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ... * This code generates _exactly_ the same sequence. */ - phase = s->ctx_data.rx.syt_offset_state; - index = phase % 13; - syt_offset = s->ctx_data.rx.last_syt_offset; + unsigned int phase = *syt_offset_state; + unsigned int index = phase % 13; + + syt_offset = *last_syt_offset; syt_offset += 1386 + ((index && !(index & 3)) || phase == 146); if (++phase >= 147) phase = 0; - s->ctx_data.rx.syt_offset_state = phase; + *syt_offset_state = phase; } } else - syt_offset = s->ctx_data.rx.last_syt_offset - TICKS_PER_CYCLE; - s->ctx_data.rx.last_syt_offset = syt_offset; + syt_offset = *last_syt_offset - TICKS_PER_CYCLE; + *last_syt_offset = syt_offset; if (syt_offset >= TICKS_PER_CYCLE) syt_offset = CIP_SYT_NO_INFO; @@ -759,7 +760,9 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s, unsigned int syt_offset; desc->cycle = compute_it_cycle(*ctx_header, s->queue_size); - syt_offset = calculate_syt_offset(s); + syt_offset = calculate_syt_offset( + &s->ctx_data.rx.last_syt_offset, + &s->ctx_data.rx.syt_offset_state, s->sfc); if (syt_offset != CIP_SYT_NO_INFO) { desc->syt = compute_syt(syt_offset, desc->cycle, s->ctx_data.rx.transfer_delay); From 274fc3558133d33311b22a962d0f362ddd281b51 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:32 +0900 Subject: [PATCH 212/428] ALSA: firewire-lib: code refactoring for data block calculation When calculating the number of data blocks per packet, some states are stored in AMDTP stream structure. This is inconvenient when reuse the calculation from non-stream structure. This commit applies refactoring to helper function for the calculation so that the function doesn't touch AMDTP stream structure. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-8-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 9041510cb6aa..efd1f2a40cf1 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -339,25 +339,26 @@ void amdtp_stream_pcm_prepare(struct amdtp_stream *s) } EXPORT_SYMBOL(amdtp_stream_pcm_prepare); -static unsigned int calculate_data_blocks(struct amdtp_stream *s, - unsigned int syt) +static unsigned int calculate_data_blocks(unsigned int *data_block_state, + bool is_blocking, bool is_no_info, + unsigned int syt_interval, enum cip_sfc sfc) { - unsigned int phase, data_blocks; + unsigned int data_blocks; /* Blocking mode. */ - if (s->flags & CIP_BLOCKING) { + if (is_blocking) { /* This module generate empty packet for 'no data'. */ - if (syt == CIP_SYT_NO_INFO) + if (is_no_info) data_blocks = 0; else - data_blocks = s->syt_interval; + data_blocks = syt_interval; /* Non-blocking mode. */ } else { - if (!cip_sfc_is_base_44100(s->sfc)) { + if (!cip_sfc_is_base_44100(sfc)) { // Sample_rate / 8000 is an integer, and precomputed. - data_blocks = s->ctx_data.rx.data_block_state; + data_blocks = *data_block_state; } else { - phase = s->ctx_data.rx.data_block_state; + unsigned int phase = *data_block_state; /* * This calculates the number of data blocks per packet so that @@ -367,16 +368,16 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s, * as possible in the sequence (to prevent underruns of the * device's buffer). */ - if (s->sfc == CIP_SFC_44100) + if (sfc == CIP_SFC_44100) /* 6 6 5 6 5 6 5 ... */ data_blocks = 5 + ((phase & 1) ^ (phase == 0 || phase >= 40)); else /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */ - data_blocks = 11 * (s->sfc >> 1) + (phase == 0); - if (++phase >= (80 >> (s->sfc >> 1))) + data_blocks = 11 * (sfc >> 1) + (phase == 0); + if (++phase >= (80 >> (sfc >> 1))) phase = 0; - s->ctx_data.rx.data_block_state = phase; + *data_block_state = phase; } } @@ -769,7 +770,11 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s, } else { desc->syt = syt_offset; } - desc->data_blocks = calculate_data_blocks(s, desc->syt); + desc->data_blocks = + calculate_data_blocks(&s->ctx_data.rx.data_block_state, + !!(s->flags & CIP_BLOCKING), + desc->syt == CIP_SYT_NO_INFO, + s->syt_interval, s->sfc); if (s->flags & CIP_DBC_IS_END_EVENT) dbc = (dbc + desc->data_blocks) & 0xff; From 25babf297c570ecec28451a580987fa08b49fa92 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:33 +0900 Subject: [PATCH 213/428] ALSA: firewire-lib: add cache for packet sequence to AMDTP domain structure For future extension, storage is required to store packet sequence in incoming AMDTP stream to recover media clock for outgoing AMDTP stream. This commit adds the storage to AMDTP domain for this purpose. The packet sequence is represented by 'struct seq_desc' which has two members; syt_offset and the number of data blocks. The size of storage is decided according to the size of packet queue. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-9-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 15 ++++++++++++++- sound/firewire/amdtp-stream.h | 9 +++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index efd1f2a40cf1..f1c8611cfc70 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -1269,6 +1269,8 @@ int amdtp_domain_init(struct amdtp_domain *d) d->events_per_period = 0; + d->seq_descs = NULL; + return 0; } EXPORT_SYMBOL_GPL(amdtp_domain_init); @@ -1370,12 +1372,18 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer, amdtp_rate_table[d->irq_target->sfc]); + d->seq_descs = kcalloc(queue_size, sizeof(*d->seq_descs), GFP_KERNEL); + if (!d->seq_descs) + return -ENOMEM; + d->seq_size = queue_size; + d->seq_tail = 0; + if (ir_delay_cycle > 0) { struct fw_card *fw_card = fw_parent_device(s->unit)->card; err = get_current_cycle_time(fw_card, &cycle); if (err < 0) - return err; + goto error; // No need to care overflow in cycle field because of enough // width. @@ -1431,6 +1439,8 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) error: list_for_each_entry(s, &d->streams, list) amdtp_stream_stop(s); + kfree(d->seq_descs); + d->seq_descs = NULL; return err; } EXPORT_SYMBOL_GPL(amdtp_domain_start); @@ -1455,5 +1465,8 @@ void amdtp_domain_stop(struct amdtp_domain *d) d->events_per_period = 0; d->irq_target = NULL; + + kfree(d->seq_descs); + d->seq_descs = NULL; } EXPORT_SYMBOL_GPL(amdtp_domain_stop); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 477fbfe713e5..84a01efa5a85 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -276,6 +276,11 @@ static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s, msecs_to_jiffies(timeout)) > 0; } +struct seq_desc { + unsigned int syt_offset; + unsigned int data_blocks; +}; + struct amdtp_domain { struct list_head streams; @@ -283,6 +288,10 @@ struct amdtp_domain { unsigned int events_per_buffer; struct amdtp_stream *irq_target; + + struct seq_desc *seq_descs; + unsigned int seq_size; + unsigned int seq_tail; }; int amdtp_domain_init(struct amdtp_domain *d); From 1a4be183b3fc9eca6ef0cca68b6698f4484f6b5f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:34 +0900 Subject: [PATCH 214/428] ALSA: firewire-lib: pool ideal sequence of syt offset and data block In current implementation, sequence of syt offset and the number of data blocks is generated when packets for outgoing stream are going to be queued. This commit generates and pools the sequence independently of the processing of outgoing packets for future extension. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-10-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 68 +++++++++++++++++++++++++++++++++++ sound/firewire/amdtp-stream.h | 6 ++++ 2 files changed, 74 insertions(+) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index f1c8611cfc70..a2af598e9b9a 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -905,14 +905,63 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, } } +static void pool_ideal_seq_descs(struct amdtp_domain *d, unsigned int packets) +{ + struct amdtp_stream *irq_target = d->irq_target; + unsigned int seq_tail = d->seq_tail; + unsigned int seq_size = d->seq_size; + unsigned int min_avail; + struct amdtp_stream *s; + + min_avail = d->seq_size; + list_for_each_entry(s, &d->streams, list) { + unsigned int seq_index; + unsigned int avail; + + if (s->direction == AMDTP_IN_STREAM) + continue; + + seq_index = s->ctx_data.rx.seq_index; + avail = d->seq_tail; + if (seq_index > avail) + avail += d->seq_size; + avail -= seq_index; + + if (avail < min_avail) + min_avail = avail; + } + + while (min_avail < packets) { + struct seq_desc *desc = d->seq_descs + seq_tail; + + desc->syt_offset = calculate_syt_offset(&d->last_syt_offset, + &d->syt_offset_state, irq_target->sfc); + desc->data_blocks = calculate_data_blocks(&d->data_block_state, + !!(irq_target->flags & CIP_BLOCKING), + desc->syt_offset == CIP_SYT_NO_INFO, + irq_target->syt_interval, irq_target->sfc); + + ++seq_tail; + seq_tail %= seq_size; + + ++min_avail; + } + + d->seq_tail = seq_tail; +} + static void irq_target_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, void *header, void *private_data) { struct amdtp_stream *irq_target = private_data; struct amdtp_domain *d = irq_target->domain; + unsigned int packets = header_length / sizeof(__be32); struct amdtp_stream *s; + // Record enough entries with extra 3 cycles at least. + pool_ideal_seq_descs(d, packets + 3); + out_stream_callback(context, tstamp, header_length, header, irq_target); if (amdtp_streaming_error(irq_target)) goto error; @@ -1344,6 +1393,18 @@ static int get_current_cycle_time(struct fw_card *fw_card, int *cur_cycle) */ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) { + static const struct { + unsigned int data_block; + unsigned int syt_offset; + } *entry, initial_state[] = { + [CIP_SFC_32000] = { 4, 3072 }, + [CIP_SFC_48000] = { 6, 1024 }, + [CIP_SFC_96000] = { 12, 1024 }, + [CIP_SFC_192000] = { 24, 1024 }, + [CIP_SFC_44100] = { 0, 67 }, + [CIP_SFC_88200] = { 0, 67 }, + [CIP_SFC_176400] = { 0, 67 }, + }; unsigned int events_per_buffer = d->events_per_buffer; unsigned int events_per_period = d->events_per_period; unsigned int idle_irq_interval; @@ -1378,6 +1439,11 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) d->seq_size = queue_size; d->seq_tail = 0; + entry = &initial_state[s->sfc]; + d->data_block_state = entry->data_block; + d->syt_offset_state = entry->syt_offset; + d->last_syt_offset = TICKS_PER_CYCLE; + if (ir_delay_cycle > 0) { struct fw_card *fw_card = fw_parent_device(s->unit)->card; @@ -1414,6 +1480,7 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) } else { // IT context starts immediately. cycle_match = -1; + s->ctx_data.rx.seq_index = 0; } if (s != d->irq_target) { @@ -1427,6 +1494,7 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) s = d->irq_target; s->ctx_data.rx.events_per_period = events_per_period; s->ctx_data.rx.event_count = 0; + s->ctx_data.rx.seq_index = 0; idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period, amdtp_rate_table[d->irq_target->sfc]); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 84a01efa5a85..11cff4cafd90 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -138,6 +138,8 @@ struct amdtp_stream { struct { // To calculate CIP data blocks and tstamp. unsigned int transfer_delay; + unsigned int seq_index; + unsigned int data_block_state; unsigned int last_syt_offset; unsigned int syt_offset_state; @@ -292,6 +294,10 @@ struct amdtp_domain { struct seq_desc *seq_descs; unsigned int seq_size; unsigned int seq_tail; + + unsigned int data_block_state; + unsigned int syt_offset_state; + unsigned int last_syt_offset; }; int amdtp_domain_init(struct amdtp_domain *d); From 69efd5c4bd4c0e5e0d5388aa21d71d1313714a0e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 8 May 2020 13:36:35 +0900 Subject: [PATCH 215/428] ALSA: firewire-lib: use sequence of syt offset and data block on pool in AMDTP domain In previous commit, the sequence of syt offset and the number of data blocks per packet is calculated for pool in AMDTP domain structure in advance of processing outgoing packets. This commit uses the sequence for outgoing packet processing to obsolete per-stream processing of the sequence. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200508043635.349339-11-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 56 +++++++++++++---------------------- sound/firewire/amdtp-stream.h | 4 --- 2 files changed, 20 insertions(+), 40 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index a2af598e9b9a..f8586f75441d 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -747,34 +747,30 @@ static unsigned int compute_syt(unsigned int syt_offset, unsigned int cycle, return syt & CIP_SYT_MASK; } -static void generate_ideal_pkt_descs(struct amdtp_stream *s, - struct pkt_desc *descs, - const __be32 *ctx_header, - unsigned int packets) +static void generate_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs, + const __be32 *ctx_header, unsigned int packets, + const struct seq_desc *seq_descs, + unsigned int seq_size) { unsigned int dbc = s->data_block_counter; + unsigned int seq_index = s->ctx_data.rx.seq_index; int i; for (i = 0; i < packets; ++i) { struct pkt_desc *desc = descs + i; unsigned int index = (s->packet_index + i) % s->queue_size; - unsigned int syt_offset; + const struct seq_desc *seq = seq_descs + seq_index; + unsigned int syt; desc->cycle = compute_it_cycle(*ctx_header, s->queue_size); - syt_offset = calculate_syt_offset( - &s->ctx_data.rx.last_syt_offset, - &s->ctx_data.rx.syt_offset_state, s->sfc); - if (syt_offset != CIP_SYT_NO_INFO) { - desc->syt = compute_syt(syt_offset, desc->cycle, - s->ctx_data.rx.transfer_delay); - } else { - desc->syt = syt_offset; + + syt = seq->syt_offset; + if (syt != CIP_SYT_NO_INFO) { + syt = compute_syt(syt, desc->cycle, + s->ctx_data.rx.transfer_delay); } - desc->data_blocks = - calculate_data_blocks(&s->ctx_data.rx.data_block_state, - !!(s->flags & CIP_BLOCKING), - desc->syt == CIP_SYT_NO_INFO, - s->syt_interval, s->sfc); + desc->syt = syt; + desc->data_blocks = seq->data_blocks; if (s->flags & CIP_DBC_IS_END_EVENT) dbc = (dbc + desc->data_blocks) & 0xff; @@ -786,10 +782,13 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s, desc->ctx_payload = s->buffer.packets[index].buffer; + seq_index = (seq_index + 1) % seq_size; + ++ctx_header; } s->data_block_counter = dbc; + s->ctx_data.rx.seq_index = seq_index; } static inline void cancel_stream(struct amdtp_stream *s) @@ -818,6 +817,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, void *private_data) { struct amdtp_stream *s = private_data; + const struct amdtp_domain *d = s->domain; const __be32 *ctx_header = header; unsigned int events_per_period = s->ctx_data.rx.events_per_period; unsigned int event_count = s->ctx_data.rx.event_count; @@ -830,7 +830,8 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, // Calculate the number of packets in buffer and check XRUN. packets = header_length / sizeof(*ctx_header); - generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets); + generate_pkt_descs(s, s->pkt_descs, ctx_header, packets, d->seq_descs, + d->seq_size); process_ctx_payloads(s, s->pkt_descs, packets); @@ -1037,18 +1038,6 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, int start_cycle, unsigned int queue_size, unsigned int idle_irq_interval) { - static const struct { - unsigned int data_block; - unsigned int syt_offset; - } *entry, initial_state[] = { - [CIP_SFC_32000] = { 4, 3072 }, - [CIP_SFC_48000] = { 6, 1024 }, - [CIP_SFC_96000] = { 12, 1024 }, - [CIP_SFC_192000] = { 24, 1024 }, - [CIP_SFC_44100] = { 0, 67 }, - [CIP_SFC_88200] = { 0, 67 }, - [CIP_SFC_176400] = { 0, 67 }, - }; bool is_irq_target = (s == s->domain->irq_target); unsigned int ctx_header_size; unsigned int max_ctx_payload_size; @@ -1072,12 +1061,7 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, s->data_block_counter = UINT_MAX; } else { - entry = &initial_state[s->sfc]; - s->data_block_counter = 0; - 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 */ diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 11cff4cafd90..703b710aaf7f 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -140,10 +140,6 @@ struct amdtp_stream { unsigned int transfer_delay; unsigned int seq_index; - unsigned int data_block_state; - unsigned int last_syt_offset; - unsigned int syt_offset_state; - // To generate CIP header. unsigned int fdf; int syt_override; From 28d4adc4257cd2e119df17aa7e9d18cdf607f23d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 7 May 2020 15:27:35 +0800 Subject: [PATCH 216/428] ASoC: SOF: Intel: Fix unused variable warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When CONFIG_SND_SOC_SOF_BAYTRAIL is not set, gcc warns: sound/soc/sof/intel/byt.c:85:41: warning: ‘cht_debugfs’ defined but not used [-Wunused-const-variable=] static const struct snd_sof_debugfs_map cht_debugfs[] = { ^~~~~~~~~~~ Move the variable inside #ifdef Reported-by: Hulk Robot Suggested-by: Joe Perches Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200507072735.16588-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 54 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index f872bb1f2682..3747f2c2c28b 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -82,33 +82,6 @@ static const struct snd_sof_debugfs_map byt_debugfs[] = { SOF_DEBUGFS_ACCESS_ALWAYS}, }; -static const struct snd_sof_debugfs_map cht_debugfs[] = { - {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"dmac2", BYT_DSP_BAR, DMAC2_OFFSET, DMAC_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE, - SOF_DEBUGFS_ACCESS_D0_ONLY}, - {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE, - SOF_DEBUGFS_ACCESS_D0_ONLY}, - {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_CHT, - SOF_DEBUGFS_ACCESS_ALWAYS}, -}; - static void byt_host_done(struct snd_sof_dev *sdev); static void byt_dsp_done(struct snd_sof_dev *sdev); static void byt_get_reply(struct snd_sof_dev *sdev); @@ -681,6 +654,33 @@ EXPORT_SYMBOL_NS(tng_chip_info, SND_SOC_SOF_MERRIFIELD); #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +static const struct snd_sof_debugfs_map cht_debugfs[] = { + {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"dmac2", BYT_DSP_BAR, DMAC2_OFFSET, DMAC_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE, + SOF_DEBUGFS_ACCESS_D0_ONLY}, + {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE, + SOF_DEBUGFS_ACCESS_D0_ONLY}, + {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_CHT, + SOF_DEBUGFS_ACCESS_ALWAYS}, +}; + static int byt_acpi_probe(struct snd_sof_dev *sdev) { struct snd_sof_pdata *pdata = sdev->pdata; From 2d6201ee1123325c089008570bd5ddea3c5b131a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 May 2020 14:22:28 -0500 Subject: [PATCH 217/428] ASoC: soc-core: Replace zero-length array with flexible-array The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] sizeof(flexible-array-member) triggers a warning because flexible array members have incomplete type[1]. There are some instances of code in which the sizeof operator is being incorrectly/erroneously applied to zero-length arrays and the result is zero. Such instances may be hiding some bugs. So, this work (flexible-array member conversions) will also help to get completely rid of those sorts of issues. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200507192228.GA16355@embeddedor Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 2 +- include/sound/soc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 08495f8d86dc..cc3dcb815282 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -689,7 +689,7 @@ struct snd_soc_dapm_context { /* A list of widgets associated with an object, typically a snd_kcontrol */ struct snd_soc_dapm_widget_list { int num_widgets; - struct snd_soc_dapm_widget *widgets[0]; + struct snd_soc_dapm_widget *widgets[]; }; #define for_each_dapm_widgets(list, i, widget) \ diff --git a/include/sound/soc.h b/include/sound/soc.h index 1288a87f9ccb..69a82487fa9b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1172,7 +1172,7 @@ struct snd_soc_pcm_runtime { unsigned int fe_compr:1; /* for Dynamic PCM */ int num_components; - struct snd_soc_component *components[0]; /* CPU/Codec/Platform */ + struct snd_soc_component *components[]; /* CPU/Codec/Platform */ }; /* see soc_new_pcm_runtime() */ #define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n] From a1304cba816e017d5acde322ee1c751e368dbe5a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 7 May 2020 23:33:51 +0200 Subject: [PATCH 218/428] ASoC: cros_ec_codec: allocate shash_desc dynamically The wov_hotword_model_put() function has multiple large variables on its stack, the largest of which is the result of SHASH_DESC_ON_STACK(). In total, this exceeds the warning limit for 32-bit architectures: sound/soc/codecs/cros_ec_codec.c:776:12: error: stack frame size of 1152 bytes in function 'wov_hotword_model_put' [-Werror,-Wframe-larger-than=] The function already has a dynamic crypto_alloc_shash() allocation, so using kmalloc() for the descriptor is correct as well and does not introduce any additional failure scenarios. With this, the stack usage of wov_hotword_model_put() gets reduced to 480 bytes in my test configuration. Fixes: b6bc07d4360d ("ASoC: cros_ec_codec: support WoV") Signed-off-by: Arnd Bergmann Reviewed-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200507213405.1869430-1-arnd@arndb.de Signed-off-by: Mark Brown --- sound/soc/codecs/cros_ec_codec.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index d3dc42aa6825..1948bc6971f6 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -108,22 +108,23 @@ static int calculate_sha256(struct cros_ec_codec_priv *priv, uint8_t *buf, uint32_t size, uint8_t *digest) { struct crypto_shash *tfm; + struct shash_desc *desc; tfm = crypto_alloc_shash("sha256", CRYPTO_ALG_TYPE_SHASH, 0); if (IS_ERR(tfm)) { dev_err(priv->dev, "can't alloc shash\n"); return PTR_ERR(tfm); } - - { - SHASH_DESC_ON_STACK(desc, tfm); - - desc->tfm = tfm; - - crypto_shash_digest(desc, buf, size, digest); - shash_desc_zero(desc); + desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); + if (!desc) { + crypto_free_shash(tfm); + return -ENOMEM; } + desc->tfm = tfm; + crypto_shash_digest(desc, buf, size, digest); + shash_desc_zero(desc); + kfree(desc); crypto_free_shash(tfm); #ifdef DEBUG From bbd6aac3ae15bef762af03bf62e35ace5c4292bd Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 10 May 2020 16:42:56 +0900 Subject: [PATCH 219/428] ALSA: fireface: fix configuration error for nominal sampling transfer frequency 128000 and 192000 are congruence modulo 32000, thus it's wrong to distinguish them as multiple of 32000 and 48000 by modulo 32000 at first. Additionally, used condition statement to detect quadruple speed can cause missing bit flag. Furthermore, counter to ensure the configuration is wrong and it causes false positive. This commit fixes the above three bugs. Cc: Fixes: 60aec494b389 ("ALSA: fireface: support allocate_resources operation in latter protocol") Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200510074301.116224-2-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-protocol-latter.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c index 0e4c3a9ed5e4..76ae568489ef 100644 --- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -107,18 +107,18 @@ static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate) int err; // Set the number of data blocks transferred in a second. - if (rate % 32000 == 0) - code = 0x00; + if (rate % 48000 == 0) + code = 0x04; else if (rate % 44100 == 0) code = 0x02; - else if (rate % 48000 == 0) - code = 0x04; + else if (rate % 32000 == 0) + code = 0x00; else return -EINVAL; if (rate >= 64000 && rate < 128000) code |= 0x08; - else if (rate >= 128000 && rate < 192000) + else if (rate >= 128000) code |= 0x10; reg = cpu_to_le32(code); @@ -140,7 +140,7 @@ static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate) if (curr_rate == rate) break; } - if (count == 10) + if (count > 10) return -ETIMEDOUT; for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); ++i) { From f4588cc425beb62e355bc2a5de5d5c83e26a74ca Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 10 May 2020 16:42:57 +0900 Subject: [PATCH 220/428] ALSA: fireface: start IR context immediately In the latter models of RME Fireface series, device start to transfer packets several dozens of milliseconds. On the other hand, ALSA fireface driver starts IR context 2 milliseconds after the start. This results in loss to handle incoming packets on the context. This commit changes to start IR context immediately instead of postponement. For Fireface 800, this affects nothing because the device transfer packets 100 milliseconds or so after the start and this is within wait timeout. Cc: Fixes: acfedcbe1ce4 ("ALSA: firewire-lib: postpone to start IR context") Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200510074301.116224-3-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-stream.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 63b79c4a5405..5452115c0ef9 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -184,7 +184,6 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) */ if (!amdtp_stream_running(&ff->rx_stream)) { int spd = fw_parent_device(ff->unit)->max_speed; - unsigned int ir_delay_cycle; err = ff->spec->protocol->begin_session(ff, rate); if (err < 0) @@ -200,14 +199,7 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) if (err < 0) goto error; - // The device postpones start of transmission mostly for several - // cycles after receiving packets firstly. - if (ff->spec->protocol == &snd_ff_protocol_ff800) - ir_delay_cycle = 800; // = 100 msec - else - ir_delay_cycle = 16; // = 2 msec - - err = amdtp_domain_start(&ff->domain, ir_delay_cycle); + err = amdtp_domain_start(&ff->domain, 0); if (err < 0) goto error; From c52f232e11077555cdd515f25376afa54ac36296 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 10 May 2020 16:42:58 +0900 Subject: [PATCH 221/428] ALSA: fireface: code refactoring to add enumeration constants for model identification In RME fireface series, version field of unit directory in configuration ROM is used to distinguish each model. The value of field is known and it's better to use enumeration constants for code representation. This commit adds enumeration constants for model identification. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200510074301.116224-4-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff.c | 6 +++--- sound/firewire/fireface/ff.h | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c index b62a4fd22407..b295e40a425d 100644 --- a/sound/firewire/fireface/ff.c +++ b/sound/firewire/fireface/ff.c @@ -189,7 +189,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { IEEE1394_MATCH_MODEL_ID, .vendor_id = OUI_RME, .specifier_id = OUI_RME, - .version = 0x000001, + .version = SND_FF_UNIT_VERSION_FF800, .model_id = 0x101800, .driver_data = (kernel_ulong_t)&spec_ff800, }, @@ -201,7 +201,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { IEEE1394_MATCH_MODEL_ID, .vendor_id = OUI_RME, .specifier_id = OUI_RME, - .version = 0x000002, + .version = SND_FF_UNIT_VERSION_FF400, .model_id = 0x101800, .driver_data = (kernel_ulong_t)&spec_ff400, }, @@ -213,7 +213,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { IEEE1394_MATCH_MODEL_ID, .vendor_id = OUI_RME, .specifier_id = OUI_RME, - .version = 0x000004, + .version = SND_FF_UNIT_VERSION_UCX, .model_id = 0x101800, .driver_data = (kernel_ulong_t)&spec_ucx, }, diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index dc7a20f75983..62ad921c3706 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -34,6 +34,12 @@ #define SND_FF_IN_MIDI_PORTS 2 #define SND_FF_OUT_MIDI_PORTS 2 +enum snd_ff_unit_version { + SND_FF_UNIT_VERSION_FF800 = 0x000001, + SND_FF_UNIT_VERSION_FF400 = 0x000002, + SND_FF_UNIT_VERSION_UCX = 0x000004, +}; + enum snd_ff_stream_mode { SND_FF_STREAM_MODE_LOW = 0, SND_FF_STREAM_MODE_MID, From 782222bab83a31f70c427b59587ada963d6c59c3 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 10 May 2020 16:42:59 +0900 Subject: [PATCH 222/428] ALSA: fireface: code refactoring to decide name of sound card This commit uses enumeration constants as index of table for the list of name of sound card. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200510074301.116224-5-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff.c | 18 ++++++++++++------ sound/firewire/fireface/ff.h | 3 +-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c index b295e40a425d..dd3cd25f2e3b 100644 --- a/sound/firewire/fireface/ff.c +++ b/sound/firewire/fireface/ff.c @@ -16,12 +16,20 @@ MODULE_LICENSE("GPL v2"); static void name_card(struct snd_ff *ff) { struct fw_device *fw_dev = fw_parent_device(ff->unit); + const char *const names[] = { + [SND_FF_UNIT_VERSION_FF800] = "Fireface800", + [SND_FF_UNIT_VERSION_FF400] = "Fireface400", + [SND_FF_UNIT_VERSION_UCX] = "FirefaceUCX", + }; + const char *name; + + name = names[ff->unit_version]; strcpy(ff->card->driver, "Fireface"); - strcpy(ff->card->shortname, ff->spec->name); - strcpy(ff->card->mixername, ff->spec->name); + strcpy(ff->card->shortname, name); + strcpy(ff->card->mixername, name); snprintf(ff->card->longname, sizeof(ff->card->longname), - "RME %s, GUID %08x%08x at %s, S%d", ff->spec->name, + "RME %s, GUID %08x%08x at %s, S%d", name, fw_dev->config_rom[3], fw_dev->config_rom[4], dev_name(&ff->unit->device), 100 << fw_dev->max_speed); } @@ -101,6 +109,7 @@ static int snd_ff_probe(struct fw_unit *unit, spin_lock_init(&ff->lock); init_waitqueue_head(&ff->hwdep_wait); + ff->unit_version = entry->version; ff->spec = (const struct snd_ff_spec *)entry->driver_data; /* Register this sound card later. */ @@ -145,7 +154,6 @@ static void snd_ff_remove(struct fw_unit *unit) } static const struct snd_ff_spec spec_ff800 = { - .name = "Fireface800", .pcm_capture_channels = {28, 20, 12}, .pcm_playback_channels = {28, 20, 12}, .midi_in_ports = 1, @@ -157,7 +165,6 @@ static const struct snd_ff_spec spec_ff800 = { }; static const struct snd_ff_spec spec_ff400 = { - .name = "Fireface400", .pcm_capture_channels = {18, 14, 10}, .pcm_playback_channels = {18, 14, 10}, .midi_in_ports = 2, @@ -169,7 +176,6 @@ static const struct snd_ff_spec spec_ff400 = { }; static const struct snd_ff_spec spec_ucx = { - .name = "FirefaceUCX", .pcm_capture_channels = {18, 14, 12}, .pcm_playback_channels = {18, 14, 12}, .midi_in_ports = 2, diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index 62ad921c3706..0c4fe7cff84d 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -49,8 +49,6 @@ enum snd_ff_stream_mode { struct snd_ff_protocol; struct snd_ff_spec { - const char *const name; - const unsigned int pcm_capture_channels[SND_FF_STREAM_MODE_COUNT]; const unsigned int pcm_playback_channels[SND_FF_STREAM_MODE_COUNT]; @@ -72,6 +70,7 @@ struct snd_ff { bool registered; struct delayed_work dwork; + enum snd_ff_unit_version unit_version; const struct snd_ff_spec *spec; /* To handle MIDI tx. */ From 062bb452b078ba481d856e1aca176e16b8b1466d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 10 May 2020 16:43:00 +0900 Subject: [PATCH 223/428] ALSA: fireface: add support for RME FireFace 802 Fireface 802 was shipped by RME GmbH in 2014. This model supports later protocol for management of isochronous communication and synchronization of sampling transmission frequency. This model consists of below ICs: * TI TSB41AB2 * Xilinx Spartan-6 FPGA XC6SLX16 * TI TMS320 C6747 * SMSC USB3250 Especially, this model just supports IEEE 1394a, against its name which evokes Fireface 800. This commit adds support for Fireface 802 (tested). Userspace applications can transfer PCM frames and MIDI messages via ALSA PCM/Rawmidi interface. I note that 4 channels for ADAt1 and ADAT2 are disabled at higher sampling transfer frequency since isochronous resources reservation fails due to bandwidth limitation of IEEE 1394a. The value read from LATTER_SYNC_STATUS register is slightly different from the one of Fireface UCX. The higher 4 bits and lower 4 bits are swapped within the same byte. Without any assist of userspace application, transmitted MIDI messages from the device are not going to be processed. For detail, please refer to my comment in code of latter protocol. $ python crpp < /sys/bus/firewire/devices/fw1/config_rom ROM header and bus information block ----------------------------------------------------------------- 400 0404ffff bus_info_length 4, crc_length 4, crc 65535 (should be 26805) 404 31333934 bus_name "1394" 408 20008000 irmc 0, cmc 0, isc 1, bmc 0, cyc_clk_acc 0, max_rec 8 (512) 40c 000a3504 company_id 000a35 | 410 38077423 device_id 0438077423 | EUI-64 000a350438077423 root directory ----------------------------------------------------------------- 414 0005ffff directory_length 5, crc 65535 (should be 9514) 418 0c0083c0 node capabilities per IEEE 1394 41c 03000a35 vendor 420 8100000b --> descriptor leaf at 44c 424 8d000007 --> eui-64 leaf at 440 428 d1000001 --> unit directory at 42c unit directory at 42c ----------------------------------------------------------------- 42c 0004ffff directory_length 4, crc 65535 (should be 45134) 430 12000a35 specifier id 434 13000005 version 438 17101800 model 43c 81000008 --> descriptor leaf at 45c eui-64 leaf at 440 ----------------------------------------------------------------- 440 0002ffff leaf_length 2, crc 65535 (should be 60131) 444 000a3504 company_id 000a35 | 448 38077423 device_id 0438077423 | EUI-64 000a350438077423 descriptor leaf at 44c ----------------------------------------------------------------- 44c 0003ffff leaf_length 3, crc 65535 (should be 469) 450 00000000 textual descriptor 454 00000000 minimal ASCII 458 524d4521 "RME!" descriptor leaf at 45c ----------------------------------------------------------------- 45c 0005ffff leaf_length 5, crc 65535 (should be 10561) 460 00000000 textual descriptor 464 00000000 minimal ASCII 468 46697265 "Fire" 46c 66616365 "face" 470 20383032 " 802" Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200510074301.116224-6-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/Kconfig | 1 + sound/firewire/fireface/ff-protocol-latter.c | 46 ++++++++++++++------ sound/firewire/fireface/ff.c | 24 ++++++++++ sound/firewire/fireface/ff.h | 1 + 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 995c2cefc222..4f39ef924a1a 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -165,5 +165,6 @@ config SND_FIREFACE * Fireface 400 * Fireface 800 * Fireface UCX + * Fireface 802 endif # SND_FIREWIRE diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c index 76ae568489ef..ea885e725950 100644 --- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -16,7 +16,8 @@ #define LATTER_SYNC_STATUS 0x0000801c0000ULL static int parse_clock_bits(u32 data, unsigned int *rate, - enum snd_ff_clock_src *src) + enum snd_ff_clock_src *src, + enum snd_ff_unit_version unit_version) { static const struct { unsigned int rate; @@ -43,6 +44,11 @@ static int parse_clock_bits(u32 data, unsigned int *rate, }; int i; + if (unit_version != SND_FF_UNIT_VERSION_UCX) { + // e.g. 0x00fe0f20 but expected 0x00eff002. + data = ((data & 0xf0f0f0f0) >> 4) | ((data & 0x0f0f0f0f) << 4); + } + for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) { rate_entry = rate_entries + i; if ((data & 0x0f000000) == rate_entry->flag) { @@ -79,7 +85,7 @@ static int latter_get_clock(struct snd_ff *ff, unsigned int *rate, return err; data = le32_to_cpu(reg); - return parse_clock_bits(data, rate, src); + return parse_clock_bits(data, rate, src, ff->unit_version); } static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable) @@ -181,14 +187,30 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate) __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; + if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) { + // For Fireface UCX. Always use the maximum number of data + // channels in data block of packet. + 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; + } else { + // For Fireface 802. Due to bandwidth limitation on + // IEEE 1394a (400 Mbps), Analog 1-12 and AES are available + // without any ADAT at quadruple speed. + if (rate >= 32000 && rate <= 48000) + flag = 0x9e; + else if (rate >= 64000 && rate <= 96000) + flag = 0x96; + else if (rate >= 128000 && rate <= 192000) + flag = 0x8e; + else + return -EINVAL; + } if (generation != fw_parent_device(ff->unit)->card->generation) { err = fw_iso_resources_update(&ff->tx_resources); @@ -207,8 +229,6 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate) if (err < 0) return err; - // Always use the maximum number of data channels in data block of - // packet. reg = cpu_to_le32(flag); return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, LATTER_ISOC_START, ®, sizeof(reg), 0); @@ -263,7 +283,7 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer } } - err = parse_clock_bits(data, &rate, &src); + err = parse_clock_bits(data, &rate, &src, ff->unit_version); if (err < 0) return; label = snd_ff_proc_get_clk_label(src); diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c index dd3cd25f2e3b..e4140116f3cc 100644 --- a/sound/firewire/fireface/ff.c +++ b/sound/firewire/fireface/ff.c @@ -20,6 +20,7 @@ static void name_card(struct snd_ff *ff) [SND_FF_UNIT_VERSION_FF800] = "Fireface800", [SND_FF_UNIT_VERSION_FF400] = "Fireface400", [SND_FF_UNIT_VERSION_UCX] = "FirefaceUCX", + [SND_FF_UNIT_VERSION_802] = "Fireface802", }; const char *name; @@ -186,6 +187,17 @@ static const struct snd_ff_spec spec_ucx = { .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull}, }; +static const struct snd_ff_spec spec_802 = { + .pcm_capture_channels = {30, 22, 14}, + .pcm_playback_channels = {30, 22, 14}, + .midi_in_ports = 1, + .midi_out_ports = 1, + .protocol = &snd_ff_protocol_latter, + .midi_high_addr = 0xffff00000034ull, + .midi_addr_range = 0x80, + .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull}, +}; + static const struct ieee1394_device_id snd_ff_id_table[] = { /* Fireface 800 */ { @@ -223,6 +235,18 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { .model_id = 0x101800, .driver_data = (kernel_ulong_t)&spec_ucx, }, + // Fireface 802. + { + .match_flags = IEEE1394_MATCH_VENDOR_ID | + IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION | + IEEE1394_MATCH_MODEL_ID, + .vendor_id = OUI_RME, + .specifier_id = OUI_RME, + .version = SND_FF_UNIT_VERSION_802, + .model_id = 0x101800, + .driver_data = (kernel_ulong_t)&spec_802, + }, {} }; MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table); diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index 0c4fe7cff84d..1282a57c009f 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -38,6 +38,7 @@ enum snd_ff_unit_version { SND_FF_UNIT_VERSION_FF800 = 0x000001, SND_FF_UNIT_VERSION_FF400 = 0x000002, SND_FF_UNIT_VERSION_UCX = 0x000004, + SND_FF_UNIT_VERSION_802 = 0x000005, }; enum snd_ff_stream_mode { From 1f65e6683267dde67a71c6bfcf71de35916be11a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 10 May 2020 16:43:01 +0900 Subject: [PATCH 224/428] ALSA: fireface: add support for RME Fireface UFX (untested) Fireface UFX was shipped by RME GmbH in 2010, and now discontinued. Although this model has some enhanced feature which Fireface 802 doesn't have (e.g. on-board USB mass storage device class, configuration interface with color display), the functionality relevant to packet communication on IEEE 1394 bus seems to be the same as Fireface 802 (e.g. available number of channels for PCM frame in each sampling transfer frequency). With the assumption, this commit adds support for Fireface UFX. In ALSA fireface driver, these two models are handled as the same one. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200510074301.116224-7-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/Kconfig | 1 + sound/firewire/fireface/ff-protocol-latter.c | 2 +- sound/firewire/fireface/ff.c | 17 +++++++++++++++-- sound/firewire/fireface/ff.h | 1 + 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 4f39ef924a1a..f7ed69d60310 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -164,6 +164,7 @@ config SND_FIREFACE Say Y here to include support for RME fireface series. * Fireface 400 * Fireface 800 + * Fireface UFX * Fireface UCX * Fireface 802 diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c index ea885e725950..8d3b23778eb2 100644 --- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -199,7 +199,7 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate) else return -EINVAL; } else { - // For Fireface 802. Due to bandwidth limitation on + // For Fireface UFX and 802. Due to bandwidth limitation on // IEEE 1394a (400 Mbps), Analog 1-12 and AES are available // without any ADAT at quadruple speed. if (rate >= 32000 && rate <= 48000) diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c index e4140116f3cc..bc39269415d2 100644 --- a/sound/firewire/fireface/ff.c +++ b/sound/firewire/fireface/ff.c @@ -19,6 +19,7 @@ static void name_card(struct snd_ff *ff) const char *const names[] = { [SND_FF_UNIT_VERSION_FF800] = "Fireface800", [SND_FF_UNIT_VERSION_FF400] = "Fireface400", + [SND_FF_UNIT_VERSION_UFX] = "FirefaceUFX", [SND_FF_UNIT_VERSION_UCX] = "FirefaceUCX", [SND_FF_UNIT_VERSION_802] = "Fireface802", }; @@ -187,7 +188,7 @@ static const struct snd_ff_spec spec_ucx = { .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull}, }; -static const struct snd_ff_spec spec_802 = { +static const struct snd_ff_spec spec_ufx_802 = { .pcm_capture_channels = {30, 22, 14}, .pcm_playback_channels = {30, 22, 14}, .midi_in_ports = 1, @@ -223,6 +224,18 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { .model_id = 0x101800, .driver_data = (kernel_ulong_t)&spec_ff400, }, + // Fireface UFX. + { + .match_flags = IEEE1394_MATCH_VENDOR_ID | + IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION | + IEEE1394_MATCH_MODEL_ID, + .vendor_id = OUI_RME, + .specifier_id = OUI_RME, + .version = SND_FF_UNIT_VERSION_UFX, + .model_id = 0x101800, + .driver_data = (kernel_ulong_t)&spec_ufx_802, + }, // Fireface UCX. { .match_flags = IEEE1394_MATCH_VENDOR_ID | @@ -245,7 +258,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { .specifier_id = OUI_RME, .version = SND_FF_UNIT_VERSION_802, .model_id = 0x101800, - .driver_data = (kernel_ulong_t)&spec_802, + .driver_data = (kernel_ulong_t)&spec_ufx_802, }, {} }; diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index 1282a57c009f..705e7df4f929 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -37,6 +37,7 @@ enum snd_ff_unit_version { SND_FF_UNIT_VERSION_FF800 = 0x000001, SND_FF_UNIT_VERSION_FF400 = 0x000002, + SND_FF_UNIT_VERSION_UFX = 0x000003, SND_FF_UNIT_VERSION_UCX = 0x000004, SND_FF_UNIT_VERSION_802 = 0x000005, }; From 07f77dd47a2ccde697fcfa3d156164cf36fe4a4d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 11 May 2020 11:25:40 +0900 Subject: [PATCH 225/428] ALSA: firewire-motu: fulfill missing entries in Kconfig This is trivial commit but fulfill missing entries in Kconfig for devices supported by ALSA firewire-motu driver. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200511022540.161363-1-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index f7ed69d60310..25778765cbfe 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -150,8 +150,12 @@ config SND_FIREWIRE_MOTU Say Y here to enable support for FireWire devices which MOTU produced: * 828mk2 * Traveler - * 828mk3 + * Ultralite + * 8pre + * 828mk3 (FireWire only) + * 828mk3 (Hybrid) * Audio Express + * 4pre To compile this driver as a module, choose M here: the module will be called snd-firewire-motu. From d9a2d100c96d3ae6253926e3f11c55242907a30c Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Mon, 11 May 2020 12:40:00 +0800 Subject: [PATCH 226/428] ASoC: mediatek: mt8183-da7219: set headset button maps Sets headset button maps. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200511044000.86161-1-tzungbi@google.com Signed-off-by: Mark Brown --- .../soc/mediatek/mt8183/mt8183-da7219-max98357.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 5b3dfa79b4ae..ffd7c931e7bb 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -6,11 +6,12 @@ // Copyright (c) 2018 MediaTek Inc. // Author: Shunli Wang +#include #include +#include +#include #include #include -#include -#include #include "mt8183-afe-common.h" #include "../../codecs/da7219-aad.h" @@ -471,9 +472,18 @@ mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) if (ret) return ret; + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + da7219_aad_jack_det(component, &priv->headset_jack); - return ret; + return 0; } static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) From 7d8785bc7adbb4dc5ba8ee06994107637848ded8 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 9 May 2020 09:33:37 +0000 Subject: [PATCH 227/428] ASoC: SOF: core: fix error return code in sof_probe_continue() Fix to return negative error code -ENOMEM from the IPC init error handling case instead of 0, as done elsewhere in this function. Fixes: c16211d6226d ("ASoC: SOF: Add Sound Open Firmware driver core") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20200509093337.78897-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 94a2cb58ab9a..ef9be4f45e27 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -176,6 +176,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) /* init the IPC */ sdev->ipc = snd_sof_ipc_init(sdev); if (!sdev->ipc) { + ret = -ENOMEM; dev_err(sdev->dev, "error: failed to init DSP IPC %d\n", ret); goto ipc_err; } From 66c705d07d784fb6b4622c6e47b6acae357472db Mon Sep 17 00:00:00 2001 From: Yongbo Zhang Date: Tue, 12 May 2020 17:30:03 +0800 Subject: [PATCH 228/428] SoC: rsnd: add interrupt support for SSI BUSIF buffer SSI BUSIF buffer is possible to overflow or underflow, especially in a hypervisor environment. If there is no interrupt support, it will eventually lead to errors in pcm data. This patch adds overflow and underflow interrupt support for SSI BUSIF buffer. Reported-by: Chen Li Signed-off-by: Yongbo Zhang Tested-by: Chen Li Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/20200512093003.28332-1-giraffesnn123@gmail.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 8 +++ sound/soc/sh/rcar/rsnd.h | 9 +++ sound/soc/sh/rcar/ssi.c | 145 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index af19010b9d88..8bd49c8a9517 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -224,6 +224,14 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884), RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888), RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE5, 0x894), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE7, 0x89c), RSND_GEN_S_REG(HDMI0_SEL, 0x9e0), RSND_GEN_S_REG(HDMI1_SEL, 0x9e4), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index ea6cbaa9743e..d47608ff5fac 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -189,6 +189,14 @@ enum rsnd_reg { SSI_SYS_STATUS5, SSI_SYS_STATUS6, SSI_SYS_STATUS7, + SSI_SYS_INT_ENABLE0, + SSI_SYS_INT_ENABLE1, + SSI_SYS_INT_ENABLE2, + SSI_SYS_INT_ENABLE3, + SSI_SYS_INT_ENABLE4, + SSI_SYS_INT_ENABLE5, + SSI_SYS_INT_ENABLE6, + SSI_SYS_INT_ENABLE7, HDMI0_SEL, HDMI1_SEL, SSI9_BUSIF0_MODE, @@ -237,6 +245,7 @@ enum rsnd_reg { #define SSI9_BUSIF_ADINR(i) (SSI9_BUSIF0_ADINR + (i)) #define SSI9_BUSIF_DALIGN(i) (SSI9_BUSIF0_DALIGN + (i)) #define SSI_SYS_STATUS(i) (SSI_SYS_STATUS0 + (i)) +#define SSI_SYS_INT_ENABLE(i) (SSI_SYS_INT_ENABLE0 + (i)) struct rsnd_priv; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 4a7d3413917f..47d5ddb526f2 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -372,6 +372,9 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, u32 wsr = ssi->wsr; int width; int is_tdm, is_tdm_split; + int id = rsnd_mod_id(mod); + int i; + u32 sys_int_enable = 0; is_tdm = rsnd_runtime_is_tdm(io); is_tdm_split = rsnd_runtime_is_tdm_split(io); @@ -447,6 +450,38 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, cr_mode = DIEN; /* PIO : enable Data interrupt */ } + /* enable busif buffer over/under run interrupt. */ + if (is_tdm || is_tdm_split) { + switch (id) { + case 0: + case 1: + case 2: + case 3: + case 4: + for (i = 0; i < 4; i++) { + sys_int_enable = rsnd_mod_read(mod, + SSI_SYS_INT_ENABLE(i * 2)); + sys_int_enable |= 0xf << (id * 4); + rsnd_mod_write(mod, + SSI_SYS_INT_ENABLE(i * 2), + sys_int_enable); + } + + break; + case 9: + for (i = 0; i < 4; i++) { + sys_int_enable = rsnd_mod_read(mod, + SSI_SYS_INT_ENABLE((i * 2) + 1)); + sys_int_enable |= 0xf << 4; + rsnd_mod_write(mod, + SSI_SYS_INT_ENABLE((i * 2) + 1), + sys_int_enable); + } + + break; + } + } + init_end: ssi->cr_own = cr_own; ssi->cr_mode = cr_mode; @@ -496,6 +531,13 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct device *dev = rsnd_priv_to_dev(priv); + int is_tdm, is_tdm_split; + int id = rsnd_mod_id(mod); + int i; + u32 sys_int_enable = 0; + + is_tdm = rsnd_runtime_is_tdm(io); + is_tdm_split = rsnd_runtime_is_tdm_split(io); if (!rsnd_ssi_is_run_mods(mod, io)) return 0; @@ -517,6 +559,38 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, ssi->wsr = 0; } + /* disable busif buffer over/under run interrupt. */ + if (is_tdm || is_tdm_split) { + switch (id) { + case 0: + case 1: + case 2: + case 3: + case 4: + for (i = 0; i < 4; i++) { + sys_int_enable = rsnd_mod_read(mod, + SSI_SYS_INT_ENABLE(i * 2)); + sys_int_enable &= ~(0xf << (id * 4)); + rsnd_mod_write(mod, + SSI_SYS_INT_ENABLE(i * 2), + sys_int_enable); + } + + break; + case 9: + for (i = 0; i < 4; i++) { + sys_int_enable = rsnd_mod_read(mod, + SSI_SYS_INT_ENABLE((i * 2) + 1)); + sys_int_enable &= ~(0xf << 4); + rsnd_mod_write(mod, + SSI_SYS_INT_ENABLE((i * 2) + 1), + sys_int_enable); + } + + break; + } + } + return 0; } @@ -622,6 +696,11 @@ static int rsnd_ssi_irq(struct rsnd_mod *mod, int enable) { u32 val = 0; + int is_tdm, is_tdm_split; + int id = rsnd_mod_id(mod); + + is_tdm = rsnd_runtime_is_tdm(io); + is_tdm_split = rsnd_runtime_is_tdm_split(io); if (rsnd_is_gen1(priv)) return 0; @@ -635,6 +714,19 @@ static int rsnd_ssi_irq(struct rsnd_mod *mod, if (enable) val = rsnd_ssi_is_dma_mode(mod) ? 0x0e000000 : 0x0f000000; + if (is_tdm || is_tdm_split) { + switch (id) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 9: + val |= 0x0000ff00; + break; + } + } + rsnd_mod_write(mod, SSI_INT_ENABLE, val); return 0; @@ -651,6 +743,12 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, u32 status; bool elapsed = false; bool stop = false; + int id = rsnd_mod_id(mod); + int i; + int is_tdm, is_tdm_split; + + is_tdm = rsnd_runtime_is_tdm(io); + is_tdm_split = rsnd_runtime_is_tdm_split(io); spin_lock(&priv->lock); @@ -672,6 +770,53 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, stop = true; } + status = 0; + + if (is_tdm || is_tdm_split) { + switch (id) { + case 0: + case 1: + case 2: + case 3: + case 4: + for (i = 0; i < 4; i++) { + status = rsnd_mod_read(mod, + SSI_SYS_STATUS(i * 2)); + status &= 0xf << (id * 4); + + if (status) { + rsnd_dbg_irq_status(dev, + "%s err status : 0x%08x\n", + rsnd_mod_name(mod), status); + rsnd_mod_write(mod, + SSI_SYS_STATUS(i * 2), + 0xf << (id * 4)); + stop = true; + break; + } + } + break; + case 9: + for (i = 0; i < 4; i++) { + status = rsnd_mod_read(mod, + SSI_SYS_STATUS((i * 2) + 1)); + status &= 0xf << 4; + + if (status) { + rsnd_dbg_irq_status(dev, + "%s err status : 0x%08x\n", + rsnd_mod_name(mod), status); + rsnd_mod_write(mod, + SSI_SYS_STATUS((i * 2) + 1), + 0xf << 4); + stop = true; + break; + } + } + break; + } + } + rsnd_ssi_status_clear(mod); rsnd_ssi_interrupt_out: spin_unlock(&priv->lock); From 6a5d6fd332624e4eee9a450bb3d18f761548822f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 7 May 2020 09:34:04 -0400 Subject: [PATCH 229/428] ASoC: Intel: baytrail: Fix register access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Baytrail has 64 bit registers, so we should use *read64* to read from it and then use proper mask values to check status. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Tested-by: Brent Lu Acked-by: Cezary Rojewski Link: https://lore.kernel.org/r/20200507133405.32251-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/baytrail/sst-baytrail-ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index 74274bd38f7a..34746fd871b0 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c @@ -666,8 +666,8 @@ static bool byt_is_dsp_busy(struct sst_dsp *dsp) { u64 ipcx; - ipcx = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); - return (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)); + ipcx = sst_dsp_shim_read64_unlocked(dsp, SST_IPCX); + return (ipcx & (SST_BYT_IPCX_BUSY | SST_BYT_IPCX_DONE)); } int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) From 6c47660e3c3acad9401f8fe1d288d4234f05549c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 7 May 2020 09:34:05 -0400 Subject: [PATCH 230/428] ASoC: Intel: Use readq to read 64 bit registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to fix issue described in: "ASoC: Intel: sst: ipc command timeout" https://patchwork.kernel.org/patch/11482829/ use readq function, which is meant to read 64 bit values from registers. On 32 bit platforms it falls back to two readl calls. Reported-by: Brent Lu Signed-off-by: Amadeusz SÅ‚awiÅ„ski Tested-by: Brent Lu Acked-by: Cezary Rojewski Link: https://lore.kernel.org/r/20200507133405.32251-2-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/sst-dsp.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c index ec66be269b69..36c077aa386e 100644 --- a/sound/soc/intel/common/sst-dsp.c +++ b/sound/soc/intel/common/sst-dsp.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include "sst-dsp.h" @@ -34,16 +34,13 @@ EXPORT_SYMBOL_GPL(sst_shim32_read); void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value) { - memcpy_toio(addr + offset, &value, sizeof(value)); + writeq(value, addr + offset); } EXPORT_SYMBOL_GPL(sst_shim32_write64); u64 sst_shim32_read64(void __iomem *addr, u32 offset) { - u64 val; - - memcpy_fromio(&val, addr + offset, sizeof(val)); - return val; + return readq(addr + offset); } EXPORT_SYMBOL_GPL(sst_shim32_read64); From 00a1aca23e71d83454485d55b5af32c5b367c99f Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:24 +0200 Subject: [PATCH 231/428] ASoC: mmp-sspa: Flip SNDRV_PCM_FMTBIT_S24_3LE on The hw_params() callback handles the 3-byte format, not SNDRV_PCM_FMTBIT_S24_LE. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-2-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 3548a2634a63..1ca6afe464c4 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -362,7 +362,7 @@ static int mmp_sspa_probe(struct snd_soc_dai *dai) #define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000 #define MMP_SSPA_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops mmp_sspa_dai_ops = { From 74fcfde748b26c68a8ab2791d9d73f698f7752d1 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:25 +0200 Subject: [PATCH 232/428] ASoC: mmp-sspa: Drop S20_3LE case It does nothing, because the corresponding bit s not flipped on in .formats and the audio SRAM DMA engine is not able to handle 20-bit transfers anyway. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-3-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 1ca6afe464c4..90a9bc81be80 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -275,9 +275,6 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_FORMAT_S16_LE: sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS); break; - case SNDRV_PCM_FORMAT_S20_3LE: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_20_BITS); - break; case SNDRV_PCM_FORMAT_S24_3LE: sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS); break; From 936b9df7a5c00db92088b3c51316d5f551ee5b2c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 11 May 2020 12:46:47 -0500 Subject: [PATCH 233/428] ASoC: Intel: Skylake: Replace zero-length array with flexible-array The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] sizeof(flexible-array-member) triggers a warning because flexible array members have incomplete type[1]. There are some instances of code in which the sizeof operator is being incorrectly/erroneously applied to zero-length arrays and the result is zero. Such instances may be hiding some bugs. So, this work (flexible-array member conversions) will also help to get completely rid of those sorts of issues. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Acked-by: Cezary Rojewski Link: https://lore.kernel.org/r/20200511174647.GA17318@embeddedor Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-atom-controls.h | 2 +- sound/soc/intel/skylake/skl-i2s.h | 2 +- sound/soc/intel/skylake/skl-topology.h | 4 ++-- sound/soc/intel/skylake/skl.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/atom/sst-atom-controls.h b/sound/soc/intel/atom/sst-atom-controls.h index 5356e954a732..620b48d2a064 100644 --- a/sound/soc/intel/atom/sst-atom-controls.h +++ b/sound/soc/intel/atom/sst-atom-controls.h @@ -410,7 +410,7 @@ struct sst_cmd_set_gain_dual { struct sst_cmd_set_params { struct sst_destination_id dst; u16 command_id; - char params[0]; + char params[]; } __packed; diff --git a/sound/soc/intel/skylake/skl-i2s.h b/sound/soc/intel/skylake/skl-i2s.h index d7c15873c0d4..dfce91e11be1 100644 --- a/sound/soc/intel/skylake/skl-i2s.h +++ b/sound/soc/intel/skylake/skl-i2s.h @@ -46,7 +46,7 @@ struct skl_i2s_config_mclk { struct skl_i2s_config_mclk_ext { u32 mdivctrl; u32 mdivr_count; - u32 mdivr[0]; + u32 mdivr[]; } __packed; struct skl_i2s_config_blob_signature { diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 06576147cc29..9889f728752c 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -119,7 +119,7 @@ struct skl_cpr_gtw_cfg { struct skl_dma_control { u32 node_id; u32 config_length; - u32 config_data[0]; + u32 config_data[]; } __packed; struct skl_cpr_cfg { @@ -152,7 +152,7 @@ struct skl_up_down_mixer_cfg { struct skl_algo_cfg { struct skl_base_cfg base_cfg; - char params[0]; + char params[]; } __packed; struct skl_base_outfmt_cfg { diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 2bfbf59277c4..26057f38a014 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -49,7 +49,7 @@ struct skl_astate_param { struct skl_astate_config { u32 count; - struct skl_astate_param astate_table[0]; + struct skl_astate_param astate_table[]; }; struct skl_fw_config { From 4e8748fcaeec073e3ba794871ce86c545e4f961f Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 12 May 2020 12:07:05 +0200 Subject: [PATCH 234/428] ASoC: ux500: mop500: Fix some refcounted resources issues There are 2 issues here: - if one of the 'of_parse_phandle' fails, calling 'mop500_of_node_put()' is a no-op because the 'mop500_dai_links' structure has not been initialized yet, so the referenced are not decremented - The reference stored in 'mop500_dai_links[i].codecs' is refcounted only once in the probe and must be decremented only once. Fixes: 39013bd60e79 ("ASoC: Ux500: Dispose of device nodes correctly") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20200512100705.246349-1-christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/ux500/mop500.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 2873e8e6f02b..cdae1190b930 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -63,10 +63,11 @@ static void mop500_of_node_put(void) { int i; - for (i = 0; i < 2; i++) { + for (i = 0; i < 2; i++) of_node_put(mop500_dai_links[i].cpus->of_node); - of_node_put(mop500_dai_links[i].codecs->of_node); - } + + /* Both links use the same codec, which is refcounted only once */ + of_node_put(mop500_dai_links[0].codecs->of_node); } static int mop500_of_probe(struct platform_device *pdev, @@ -81,7 +82,9 @@ static int mop500_of_probe(struct platform_device *pdev, if (!(msp_np[0] && msp_np[1] && codec_np)) { dev_err(&pdev->dev, "Phandle missing or invalid\n"); - mop500_of_node_put(); + for (i = 0; i < 2; i++) + of_node_put(msp_np[i]); + of_node_put(codec_np); return -EINVAL; } From ab436c974e08d9254999d7a84d86b1d4c1749230 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Thu, 7 May 2020 13:32:38 +0200 Subject: [PATCH 235/428] ASoC: rockchip-i2s: add description for rk3308 The description below is already in use for rk3308.dtsi, but was somehow never added to a document, so add "rockchip,rk3308-i2s", "rockchip,rk3066-i2s" for i2s nodes on a rk3308 platform to rockchip-i2s.yaml. One of the rk3308 i2s nodes also has a different dma layout, so change that as well. Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200507113238.7904-1-jbx6244@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/rockchip-i2s.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index a3ba2186d6a1..10f9d3ad0d48 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -24,6 +24,7 @@ properties: - rockchip,rk3188-i2s - rockchip,rk3228-i2s - rockchip,rk3288-i2s + - rockchip,rk3308-i2s - rockchip,rk3328-i2s - rockchip,rk3366-i2s - rockchip,rk3368-i2s @@ -47,14 +48,15 @@ properties: - const: i2s_hclk dmas: - items: - - description: TX DMA Channel - - description: RX DMA Channel + minItems: 1 + maxItems: 2 dma-names: - items: - - const: tx + oneOf: - const: rx + - items: + - const: tx + - const: rx power-domains: maxItems: 1 From cc2d025a81a9f9ed4d05f4f65f43a183d6f18c0c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 6 May 2020 23:21:14 +0200 Subject: [PATCH 236/428] ASoC: Intel: Skylake: Update description for HDaudio kconfig With 'ASoC: Intel: Skylake: Fix HDaudio and Dmic' series applied, warning is no longer true. Remove it and update the description. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20200506212114.8502-1-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index c8de0bb5bed9..36f547939f0a 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -209,12 +209,8 @@ config SND_SOC_INTEL_SKYLAKE_SSP_CLK config SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC bool "HDAudio codec support" help - This option broke audio on Linus' Skylake laptop in December 2018 - and the race conditions during the probe were not fixed since. - This option is DEPRECATED, all HDaudio codec support needs - to be handled by the SOF driver. - Distributions should not enable this option and there are no known - users of this capability. + If you have Intel Skylake or Kabylake with HDaudio codec + and DMIC present then enable this option by saying Y. config SND_SOC_INTEL_SKYLAKE_COMMON tristate From 03990fd58d2b7c8f7d53e514ba9b8749fac260f9 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 12 May 2020 15:43:25 +0200 Subject: [PATCH 237/428] ASoC: ti: omap-mcbsp: Fix an error handling path in 'asoc_mcbsp_probe()' If an error occurs after the call to 'omap_mcbsp_init()', the reference to 'mcbsp->fclk' must be decremented, as already done in the remove function. This can be achieved easily by using the devm_ variant of 'clk_get()' when the reference is taken in 'omap_mcbsp_init()' This fixes the leak in the probe and has the side effect to simplify both the error handling path of 'omap_mcbsp_init()' and the remove function. Signed-off-by: Christophe JAILLET Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200512134325.252073-1-christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/ti/omap-mcbsp.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 0348963f4df7..6c83b9888467 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -686,7 +686,7 @@ static int omap_mcbsp_init(struct platform_device *pdev) mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, SNDRV_PCM_STREAM_CAPTURE); - mcbsp->fclk = clk_get(&pdev->dev, "fck"); + mcbsp->fclk = devm_clk_get(&pdev->dev, "fck"); if (IS_ERR(mcbsp->fclk)) { ret = PTR_ERR(mcbsp->fclk); dev_err(mcbsp->dev, "unable to get fck: %d\n", ret); @@ -711,7 +711,7 @@ static int omap_mcbsp_init(struct platform_device *pdev) if (ret) { dev_err(mcbsp->dev, "Unable to create additional controls\n"); - goto err_thres; + return ret; } } @@ -724,8 +724,6 @@ static int omap_mcbsp_init(struct platform_device *pdev) err_st: if (mcbsp->pdata->buffer_size) sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group); -err_thres: - clk_put(mcbsp->fclk); return ret; } @@ -1442,8 +1440,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev) omap_mcbsp_st_cleanup(pdev); - clk_put(mcbsp->fclk); - return 0; } From e0b9024d2c8851b18b953823204278602bf73086 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:26 +0200 Subject: [PATCH 238/428] ASoC: mmp-sspa: A trivial typo fix "Transmit", not "Tansmit". Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-4-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/pxa/mmp-sspa.h b/sound/soc/pxa/mmp-sspa.h index 7d1b7c7325df..611063a7af68 100644 --- a/sound/soc/pxa/mmp-sspa.h +++ b/sound/soc/pxa/mmp-sspa.h @@ -38,7 +38,7 @@ #define SSPA_CTL_XFRLEN2(x) ((x) << 24) /* Transmit Frame Length in Phase 2 */ #define SSPA_CTL_XWDLEN2_MASK (7 << 21) #define SSPA_CTL_XWDLEN2(x) ((x) << 21) /* Transmit Word Length in Phase 2 */ -#define SSPA_CTL_XDATDLY(x) ((x) << 19) /* Tansmit Data Delay */ +#define SSPA_CTL_XDATDLY(x) ((x) << 19) /* Transmit Data Delay */ #define SSPA_CTL_XSSZ2_MASK (7 << 16) #define SSPA_CTL_XSSZ2(x) ((x) << 16) /* Transmit Sample Audio Size */ #define SSPA_CTL_XFRLEN1_MASK (7 << 8) From c9aeda1c94973f835b3d1b6c785a414caaf935c3 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:27 +0200 Subject: [PATCH 239/428] ASoC: mmp-sspa: Get rid of dma_params and phys_base This makes things simpler. There's no reason not to just embed the struct snd_dmaengine_dai_dma_data in struct sspa_priv and do away with an unnecessary kmalloc(). While at that, we can initialize the snd_dmaengine_dai_dma_data structures earlier. Let's also stop offsetting the source/destination of the DMA transfer by phys_base. Firstly, it's never set and is always zero. Secondly, the hardware actually ignores it, at least on a MMP2 and MMP3. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-5-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 90a9bc81be80..421ffa9fa7b1 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -29,7 +29,8 @@ */ struct sspa_priv { struct ssp_device *sspa; - struct snd_dmaengine_dai_dma_data *dma_params; + struct snd_dmaengine_dai_dma_data playback_dma_data; + struct snd_dmaengine_dai_dma_data capture_dma_data; struct clk *audio_clk; struct clk *sysclk; int dai_fmt; @@ -250,11 +251,8 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); struct ssp_device *sspa = sspa_priv->sspa; - struct snd_dmaengine_dai_dma_data *dma_params; u32 sspa_ctrl; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -293,11 +291,6 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, mmp_sspa_write_reg(sspa, SSPA_RXFIFO_UL, 0x0); } - dma_params = &sspa_priv->dma_params[substream->stream]; - dma_params->addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - (sspa->phys_base + SSPA_TXD) : - (sspa->phys_base + SSPA_RXD); - snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params); return 0; } @@ -351,6 +344,10 @@ static int mmp_sspa_probe(struct snd_soc_dai *dai) { struct sspa_priv *priv = dev_get_drvdata(dai->dev); + snd_soc_dai_init_dma_data(dai, + &priv->playback_dma_data, + &priv->capture_dma_data); + snd_soc_dai_set_drvdata(dai, priv); return 0; @@ -407,12 +404,6 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) if (priv->sspa == NULL) return -ENOMEM; - priv->dma_params = devm_kcalloc(&pdev->dev, - 2, sizeof(struct snd_dmaengine_dai_dma_data), - GFP_KERNEL); - if (priv->dma_params == NULL) - return -ENOMEM; - priv->sspa->mmio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->sspa->mmio_base)) return PTR_ERR(priv->sspa->mmio_base); @@ -434,6 +425,10 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) priv->dai_fmt = (unsigned int) -1; platform_set_drvdata(pdev, priv); + /* You know, these addresses are actually ignored. */ + priv->playback_dma_data.addr = SSPA_TXD; + priv->capture_dma_data.addr = SSPA_RXD; + return devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component, &mmp_sspa_dai, 1); } From 724da05378ba7af6e273451a2c3f565a3315a9db Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:28 +0200 Subject: [PATCH 240/428] ASoC: mmp-sspa: Add support for soc-generic-dmaengine-pcm This makes the driver usable with the mmp_tdma drier via soc-generic-dmaengine-pcm. This is conditionalized on DT node (support for DT is added by a later patch). A custom mmap callback that creates a NC mapping is used instead of the default WC one, because with write-combining some bytes don't seem to make it through for reasons unknown to me. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-6-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 421ffa9fa7b1..6e4b63d0c589 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -386,8 +386,54 @@ static struct snd_soc_dai_driver mmp_sspa_dai = { .ops = &mmp_sspa_dai_ops, }; +#define MMP_PCM_INFO (SNDRV_PCM_INFO_MMAP | \ + SNDRV_PCM_INFO_MMAP_VALID | \ + SNDRV_PCM_INFO_INTERLEAVED | \ + SNDRV_PCM_INFO_PAUSE | \ + SNDRV_PCM_INFO_RESUME | \ + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) + +static const struct snd_pcm_hardware mmp_pcm_hardware[] = { + { + .info = MMP_PCM_INFO, + .period_bytes_min = 1024, + .period_bytes_max = 2048, + .periods_min = 2, + .periods_max = 32, + .buffer_bytes_max = 4096, + .fifo_size = 32, + }, + { + .info = MMP_PCM_INFO, + .period_bytes_min = 1024, + .period_bytes_max = 2048, + .periods_min = 2, + .periods_max = 32, + .buffer_bytes_max = 4096, + .fifo_size = 32, + }, +}; + +static const struct snd_dmaengine_pcm_config mmp_pcm_config = { + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, + .pcm_hardware = mmp_pcm_hardware, + .prealloc_buffer_size = 4096, +}; + +static int mmp_pcm_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + return remap_pfn_range(vma, vma->vm_start, + substream->dma_buffer.addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + static const struct snd_soc_component_driver mmp_sspa_component = { .name = "mmp-sspa", + .mmap = mmp_pcm_mmap, }; static int asoc_mmp_sspa_probe(struct platform_device *pdev) @@ -425,10 +471,21 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) priv->dai_fmt = (unsigned int) -1; platform_set_drvdata(pdev, priv); + priv->playback_dma_data.maxburst = 4; + priv->capture_dma_data.maxburst = 4; /* You know, these addresses are actually ignored. */ priv->playback_dma_data.addr = SSPA_TXD; priv->capture_dma_data.addr = SSPA_RXD; + if (pdev->dev.of_node) { + int ret; + + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, + &mmp_pcm_config, 0); + if (ret) + return ret; + } + return devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component, &mmp_sspa_dai, 1); } From 3c4e89df3b45348dc0ee01a2ef1be710f7424ff7 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:29 +0200 Subject: [PATCH 241/428] ASoC: mmp-sspa: Remove the embedded struct ssp_device The "serial port" it represents is actually a SPI controller -- it's not clear why would the audio serial interface embed it. We're only using the mmio_base and clk fields. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-7-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 129 ++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 69 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 6e4b63d0c589..7a706b1d2588 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -28,26 +27,27 @@ * SSPA audio private data */ struct sspa_priv { - struct ssp_device *sspa; + void __iomem *mmio_base; struct snd_dmaengine_dai_dma_data playback_dma_data; struct snd_dmaengine_dai_dma_data capture_dma_data; + struct clk *clk; struct clk *audio_clk; struct clk *sysclk; int dai_fmt; int running_cnt; }; -static void mmp_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val) +static void mmp_sspa_write_reg(struct sspa_priv *sspa, u32 reg, u32 val) { __raw_writel(val, sspa->mmio_base + reg); } -static u32 mmp_sspa_read_reg(struct ssp_device *sspa, u32 reg) +static u32 mmp_sspa_read_reg(struct sspa_priv *sspa, u32 reg) { return __raw_readl(sspa->mmio_base + reg); } -static void mmp_sspa_tx_enable(struct ssp_device *sspa) +static void mmp_sspa_tx_enable(struct sspa_priv *sspa) { unsigned int sspa_sp; @@ -57,7 +57,7 @@ static void mmp_sspa_tx_enable(struct ssp_device *sspa) mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); } -static void mmp_sspa_tx_disable(struct ssp_device *sspa) +static void mmp_sspa_tx_disable(struct sspa_priv *sspa) { unsigned int sspa_sp; @@ -67,7 +67,7 @@ static void mmp_sspa_tx_disable(struct ssp_device *sspa) mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); } -static void mmp_sspa_rx_enable(struct ssp_device *sspa) +static void mmp_sspa_rx_enable(struct sspa_priv *sspa) { unsigned int sspa_sp; @@ -77,7 +77,7 @@ static void mmp_sspa_rx_enable(struct ssp_device *sspa) mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); } -static void mmp_sspa_rx_disable(struct ssp_device *sspa) +static void mmp_sspa_rx_disable(struct sspa_priv *sspa) { unsigned int sspa_sp; @@ -90,10 +90,10 @@ static void mmp_sspa_rx_disable(struct ssp_device *sspa) static int mmp_sspa_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai); + struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); - clk_enable(priv->sysclk); - clk_enable(priv->sspa->clk); + clk_enable(sspa->sysclk); + clk_enable(sspa->clk); return 0; } @@ -101,10 +101,10 @@ static int mmp_sspa_startup(struct snd_pcm_substream *substream, static void mmp_sspa_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai); + struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); - clk_disable(priv->sspa->clk); - clk_disable(priv->sysclk); + clk_disable(sspa->clk); + clk_disable(sspa->sysclk); } @@ -114,12 +114,12 @@ static void mmp_sspa_shutdown(struct snd_pcm_substream *substream, static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); + struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); int ret = 0; switch (clk_id) { case MMP_SSPA_CLK_AUDIO: - ret = clk_set_rate(priv->audio_clk, freq); + ret = clk_set_rate(sspa->audio_clk, freq); if (ret) return ret; break; @@ -138,17 +138,17 @@ static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { - struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); + struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); int ret = 0; switch (pll_id) { case MMP_SYSCLK: - ret = clk_set_rate(priv->sysclk, freq_out); + ret = clk_set_rate(sspa->sysclk, freq_out); if (ret) return ret; break; case MMP_SSPA_CLK: - ret = clk_set_rate(priv->sspa->clk, freq_out); + ret = clk_set_rate(sspa->clk, freq_out); if (ret) return ret; break; @@ -167,18 +167,17 @@ static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai); - struct ssp_device *sspa = sspa_priv->sspa; + struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); u32 sspa_sp, sspa_ctrl; /* check if we need to change anything at all */ - if (sspa_priv->dai_fmt == fmt) + if (sspa->dai_fmt == fmt) return 0; /* we can only change the settings if the port is not in use */ if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) || (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) { - dev_err(sspa->dev, + dev_err(cpu_dai->dev, "can't change hardware dai format: stream is in use\n"); return -EINVAL; } @@ -239,7 +238,7 @@ static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, * we have to defer some things until hw_params() where we * know parameters like the sample size. */ - sspa_priv->dai_fmt = fmt; + sspa->dai_fmt = fmt; return 0; } @@ -251,8 +250,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); - struct ssp_device *sspa = sspa_priv->sspa; + struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); u32 sspa_ctrl; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -297,8 +295,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); - struct ssp_device *sspa = sspa_priv->sspa; + struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); int ret = 0; switch (cmd) { @@ -311,25 +308,25 @@ static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd, * enabled or not; if has been enabled by another * stream, do not enable again. */ - if (!sspa_priv->running_cnt) + if (!sspa->running_cnt) mmp_sspa_rx_enable(sspa); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) mmp_sspa_tx_enable(sspa); - sspa_priv->running_cnt++; + sspa->running_cnt++; break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - sspa_priv->running_cnt--; + sspa->running_cnt--; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) mmp_sspa_tx_disable(sspa); /* have no capture stream, disable rx port */ - if (!sspa_priv->running_cnt) + if (!sspa->running_cnt) mmp_sspa_rx_disable(sspa); break; @@ -342,15 +339,14 @@ static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd, static int mmp_sspa_probe(struct snd_soc_dai *dai) { - struct sspa_priv *priv = dev_get_drvdata(dai->dev); + struct sspa_priv *sspa = dev_get_drvdata(dai->dev); snd_soc_dai_init_dma_data(dai, - &priv->playback_dma_data, - &priv->capture_dma_data); + &sspa->playback_dma_data, + &sspa->capture_dma_data); - snd_soc_dai_set_drvdata(dai, priv); + snd_soc_dai_set_drvdata(dai, sspa); return 0; - } #define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000 @@ -438,44 +434,39 @@ static const struct snd_soc_component_driver mmp_sspa_component = { static int asoc_mmp_sspa_probe(struct platform_device *pdev) { - struct sspa_priv *priv; + struct sspa_priv *sspa; - priv = devm_kzalloc(&pdev->dev, + sspa = devm_kzalloc(&pdev->dev, sizeof(struct sspa_priv), GFP_KERNEL); - if (!priv) + if (!sspa) return -ENOMEM; - priv->sspa = devm_kzalloc(&pdev->dev, - sizeof(struct ssp_device), GFP_KERNEL); - if (priv->sspa == NULL) - return -ENOMEM; + sspa->mmio_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(sspa->mmio_base)) + return PTR_ERR(sspa->mmio_base); - priv->sspa->mmio_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->sspa->mmio_base)) - return PTR_ERR(priv->sspa->mmio_base); + sspa->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(sspa->clk)) + return PTR_ERR(sspa->clk); - priv->sspa->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(priv->sspa->clk)) - return PTR_ERR(priv->sspa->clk); + sspa->audio_clk = clk_get(NULL, "mmp-audio"); + if (IS_ERR(sspa->audio_clk)) + return PTR_ERR(sspa->audio_clk); - priv->audio_clk = clk_get(NULL, "mmp-audio"); - if (IS_ERR(priv->audio_clk)) - return PTR_ERR(priv->audio_clk); - - priv->sysclk = clk_get(NULL, "mmp-sysclk"); - if (IS_ERR(priv->sysclk)) { - clk_put(priv->audio_clk); - return PTR_ERR(priv->sysclk); + sspa->sysclk = clk_get(NULL, "mmp-sysclk"); + if (IS_ERR(sspa->sysclk)) { + clk_put(sspa->audio_clk); + return PTR_ERR(sspa->sysclk); } - clk_enable(priv->audio_clk); - priv->dai_fmt = (unsigned int) -1; - platform_set_drvdata(pdev, priv); + clk_enable(sspa->audio_clk); + sspa->dai_fmt = (unsigned int) -1; + platform_set_drvdata(pdev, sspa); - priv->playback_dma_data.maxburst = 4; - priv->capture_dma_data.maxburst = 4; + sspa->playback_dma_data.maxburst = 4; + sspa->capture_dma_data.maxburst = 4; /* You know, these addresses are actually ignored. */ - priv->playback_dma_data.addr = SSPA_TXD; - priv->capture_dma_data.addr = SSPA_RXD; + sspa->playback_dma_data.addr = SSPA_TXD; + sspa->capture_dma_data.addr = SSPA_RXD; if (pdev->dev.of_node) { int ret; @@ -492,11 +483,11 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) static int asoc_mmp_sspa_remove(struct platform_device *pdev) { - struct sspa_priv *priv = platform_get_drvdata(pdev); + struct sspa_priv *sspa = platform_get_drvdata(pdev); - clk_disable(priv->audio_clk); - clk_put(priv->audio_clk); - clk_put(priv->sysclk); + clk_disable(sspa->audio_clk); + clk_put(sspa->audio_clk); + clk_put(sspa->sysclk); return 0; } From 8ecdcac8792b6787ecb2341d25cb82165cf0129d Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:30 +0200 Subject: [PATCH 242/428] ASoC: mmp-sspa: Prepare/unprepare the clocks The driver enables the clocks without preparing them and disables without unpreparing afterwards. Fix that. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-8-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 7a706b1d2588..a66e594b1072 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -92,8 +92,8 @@ static int mmp_sspa_startup(struct snd_pcm_substream *substream, { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); - clk_enable(sspa->sysclk); - clk_enable(sspa->clk); + clk_prepare_enable(sspa->sysclk); + clk_prepare_enable(sspa->clk); return 0; } @@ -103,8 +103,8 @@ static void mmp_sspa_shutdown(struct snd_pcm_substream *substream, { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); - clk_disable(sspa->clk); - clk_disable(sspa->sysclk); + clk_disable_unprepare(sspa->clk); + clk_disable_unprepare(sspa->sysclk); } @@ -458,7 +458,7 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) clk_put(sspa->audio_clk); return PTR_ERR(sspa->sysclk); } - clk_enable(sspa->audio_clk); + clk_prepare_enable(sspa->audio_clk); sspa->dai_fmt = (unsigned int) -1; platform_set_drvdata(pdev, sspa); @@ -485,7 +485,7 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev) { struct sspa_priv *sspa = platform_get_drvdata(pdev); - clk_disable(sspa->audio_clk); + clk_disable_unprepare(sspa->audio_clk); clk_put(sspa->audio_clk); clk_put(sspa->sysclk); return 0; From 7d98cc648253c362ebfc582b11095a0e3f001896 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:31 +0200 Subject: [PATCH 243/428] ASoC: mmp-sspa: Add support for the runtime power management Only turn on the Audio island when it's in use. This requires keeping track of control register contents instead of reloading them back from hardware, because they're lost when the power is off. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-9-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 126 ++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index a66e594b1072..9cb17c4fb0c8 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -33,8 +34,9 @@ struct sspa_priv { struct clk *clk; struct clk *audio_clk; struct clk *sysclk; - int dai_fmt; int running_cnt; + u32 sp; + u32 ctrl; }; static void mmp_sspa_write_reg(struct sspa_priv *sspa, u32 reg, u32 val) @@ -49,9 +51,9 @@ static u32 mmp_sspa_read_reg(struct sspa_priv *sspa, u32 reg) static void mmp_sspa_tx_enable(struct sspa_priv *sspa) { - unsigned int sspa_sp; + unsigned int sspa_sp = sspa->sp; - sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP); + sspa_sp &= ~SSPA_SP_MSL; sspa_sp |= SSPA_SP_S_EN; sspa_sp |= SSPA_SP_WEN; mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); @@ -59,9 +61,9 @@ static void mmp_sspa_tx_enable(struct sspa_priv *sspa) static void mmp_sspa_tx_disable(struct sspa_priv *sspa) { - unsigned int sspa_sp; + unsigned int sspa_sp = sspa->sp; - sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP); + sspa_sp &= ~SSPA_SP_MSL; sspa_sp &= ~SSPA_SP_S_EN; sspa_sp |= SSPA_SP_WEN; mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); @@ -69,9 +71,8 @@ static void mmp_sspa_tx_disable(struct sspa_priv *sspa) static void mmp_sspa_rx_enable(struct sspa_priv *sspa) { - unsigned int sspa_sp; + unsigned int sspa_sp = sspa->sp; - sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP); sspa_sp |= SSPA_SP_S_EN; sspa_sp |= SSPA_SP_WEN; mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); @@ -79,9 +80,8 @@ static void mmp_sspa_rx_enable(struct sspa_priv *sspa) static void mmp_sspa_rx_disable(struct sspa_priv *sspa) { - unsigned int sspa_sp; + unsigned int sspa_sp = sspa->sp; - sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP); sspa_sp &= ~SSPA_SP_S_EN; sspa_sp |= SSPA_SP_WEN; mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); @@ -160,35 +160,20 @@ static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, } /* - * Set up the sspa dai format. The sspa port must be inactive - * before calling this function as the physical - * interface format is changed. + * Set up the sspa dai format. */ static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); - u32 sspa_sp, sspa_ctrl; - - /* check if we need to change anything at all */ - if (sspa->dai_fmt == fmt) - return 0; - - /* we can only change the settings if the port is not in use */ - if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) || - (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) { - dev_err(cpu_dai->dev, - "can't change hardware dai format: stream is in use\n"); - return -EINVAL; - } /* reset port settings */ - sspa_sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH; - sspa_ctrl = 0; + sspa->sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH; + sspa->ctrl = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - sspa_sp |= SSPA_SP_MSL; + sspa->sp |= SSPA_SP_MSL; break; case SND_SOC_DAIFMT_CBM_CFM: break; @@ -198,7 +183,7 @@ static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: - sspa_sp |= SSPA_SP_FSP; + sspa->sp |= SSPA_SP_FSP; break; default: return -EINVAL; @@ -206,39 +191,18 @@ static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - sspa_sp |= SSPA_TXSP_FPER(63); - sspa_sp |= SSPA_SP_FWID(31); - sspa_ctrl |= SSPA_CTL_XDATDLY(1); + sspa->sp |= SSPA_TXSP_FPER(63); + sspa->sp |= SSPA_SP_FWID(31); + sspa->ctrl |= SSPA_CTL_XDATDLY(1); break; default: return -EINVAL; } - mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); - mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); - - sspa_sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH); - mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); - mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); - - /* - * FIXME: hw issue, for the tx serial port, - * can not config the master/slave mode; - * so must clean this bit. - * The master/slave mode has been set in the - * rx port. - */ - sspa_sp &= ~SSPA_SP_MSL; - mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); - - mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); - mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl); - /* Since we are configuring the timings for the format by hand * we have to defer some things until hw_params() where we * know parameters like the sample size. */ - sspa->dai_fmt = fmt; return 0; } @@ -251,12 +215,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); - u32 sspa_ctrl; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_TXCTL); - else - sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_RXCTL); + u32 sspa_ctrl = sspa->ctrl; sspa_ctrl &= ~SSPA_CTL_XFRLEN1_MASK; sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1); @@ -427,9 +386,55 @@ static int mmp_pcm_mmap(struct snd_soc_component *component, vma->vm_end - vma->vm_start, vma->vm_page_prot); } +static int mmp_sspa_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct sspa_priv *sspa = snd_soc_component_get_drvdata(component); + + pm_runtime_get_sync(component->dev); + + /* we can only change the settings if the port is not in use */ + if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) || + (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) { + dev_err(component->dev, + "can't change hardware dai format: stream is in use\n"); + return -EBUSY; + } + + mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa->sp); + mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa->sp); + + sspa->sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH); + mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa->sp); + mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa->sp); + + /* + * FIXME: hw issue, for the tx serial port, + * can not config the master/slave mode; + * so must clean this bit. + * The master/slave mode has been set in the + * rx port. + */ + mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa->sp & ~SSPA_SP_MSL); + + mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa->ctrl); + mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa->ctrl); + + return 0; +} + +static int mmp_sspa_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + pm_runtime_put_sync(component->dev); + return 0; +} + static const struct snd_soc_component_driver mmp_sspa_component = { .name = "mmp-sspa", .mmap = mmp_pcm_mmap, + .open = mmp_sspa_open, + .close = mmp_sspa_close, }; static int asoc_mmp_sspa_probe(struct platform_device *pdev) @@ -458,8 +463,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) clk_put(sspa->audio_clk); return PTR_ERR(sspa->sysclk); } + pm_runtime_enable(&pdev->dev); clk_prepare_enable(sspa->audio_clk); - sspa->dai_fmt = (unsigned int) -1; platform_set_drvdata(pdev, sspa); sspa->playback_dma_data.maxburst = 4; @@ -486,6 +491,7 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev) struct sspa_priv *sspa = platform_get_drvdata(pdev); clk_disable_unprepare(sspa->audio_clk); + pm_runtime_disable(&pdev->dev); clk_put(sspa->audio_clk); clk_put(sspa->sysclk); return 0; From 39ec7e9b699910792468cf41a179d9930052e8ff Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:32 +0200 Subject: [PATCH 244/428] ASoC: mmp-sspa: Set appropriate bus format for given bit width The values set by set_dai_fmt() and hw_params() seem to be tailored only for 32-bit formats. Negotiate the correct ones in hw_params() callback instead. This was essentially copied from the OLPC kernel driver and tested to fix wrong audio output for non-32bit formats. The documentation is not available. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-10-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 40 ++++++++++++++++++++++++++++------------ sound/soc/pxa/mmp-sspa.h | 2 ++ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 9cb17c4fb0c8..86277471974a 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -191,8 +191,6 @@ static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - sspa->sp |= SSPA_TXSP_FPER(63); - sspa->sp |= SSPA_SP_FWID(31); sspa->ctrl |= SSPA_CTL_XDATDLY(1); break; default: @@ -216,30 +214,48 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); u32 sspa_ctrl = sspa->ctrl; - - sspa_ctrl &= ~SSPA_CTL_XFRLEN1_MASK; - sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1); - sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK; - sspa_ctrl |= SSPA_CTL_XWDLEN1(SSPA_CTL_32_BITS); - sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK; + int bits; + int bitval; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_8_BITS); + bits = 8; + bitval = SSPA_CTL_8_BITS; break; case SNDRV_PCM_FORMAT_S16_LE: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS); + bits = 16; + bitval = SSPA_CTL_16_BITS; break; case SNDRV_PCM_FORMAT_S24_3LE: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS); + bits = 24; + bitval = SSPA_CTL_24_BITS; break; case SNDRV_PCM_FORMAT_S32_LE: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_32_BITS); + bits = 32; + bitval = SSPA_CTL_32_BITS; break; default: return -EINVAL; } + if (params_channels(params) == 2) + sspa_ctrl |= SSPA_CTL_XPH; + + sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK; + sspa_ctrl |= SSPA_CTL_XWDLEN1(bitval); + + sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK; + sspa_ctrl |= SSPA_CTL_XSSZ1(bitval); + + sspa_ctrl &= ~SSPA_CTL_XSSZ2_MASK; + sspa_ctrl |= SSPA_CTL_XSSZ2(bitval); + + sspa->sp &= ~SSPA_SP_FWID_MASK; + sspa->sp |= SSPA_SP_FWID(bits - 1); + + sspa->sp &= ~SSPA_TXSP_FPER_MASK; + sspa->sp |= SSPA_TXSP_FPER(bits * 2 - 1); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1); diff --git a/sound/soc/pxa/mmp-sspa.h b/sound/soc/pxa/mmp-sspa.h index 611063a7af68..328969b57ad1 100644 --- a/sound/soc/pxa/mmp-sspa.h +++ b/sound/soc/pxa/mmp-sspa.h @@ -63,7 +63,9 @@ #define SSPA_SP_FFLUSH (1 << 2) /* FIFO Flush */ #define SSPA_SP_S_RST (1 << 1) /* Active High Reset Signal */ #define SSPA_SP_S_EN (1 << 0) /* Serial Clock Domain Enable */ +#define SSPA_SP_FWID_MASK (0x3f << 20) #define SSPA_SP_FWID(x) ((x) << 20) /* Frame-Sync Width */ +#define SSPA_TXSP_FPER_MASK (0x3f << 4) #define SSPA_TXSP_FPER(x) ((x) << 4) /* Frame-Sync Active */ /* sspa clock sources */ From 65e412a01bc0161175a962abd5a7fef6a62d5c8e Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 13 May 2020 13:30:35 +0800 Subject: [PATCH 245/428] ASoC: wm8962: Use force clear for WM8962_SYSCLK_ENA after reset When CLOCKING2 is non-volatile register, we need force clear the WM8962_SYSCLK_ENA bit after reset, for the value in cache maybe 0 but in hardware it is 1. Otherwise there will issue as below statement in driver. /* SYSCLK defaults to on; make sure it is off so we can safely * write to registers if the device is declocked. Fixes: c38b608504aa ("ASoC: wm8962: set CLOCKING2 as non-volatile register") Signed-off-by: Shengjiu Wang Acked-by: Charles Keepax Link: https://lore.kernel.org/r/1589347835-20554-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 0a2cfff44441..08d19df8a700 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3798,8 +3798,8 @@ static int wm8962_runtime_resume(struct device *dev) /* SYSCLK defaults to on; make sure it is off so we can safely * write to registers if the device is declocked. */ - regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2, - WM8962_SYSCLK_ENA, 0); + regmap_write_bits(wm8962->regmap, WM8962_CLOCKING2, + WM8962_SYSCLK_ENA, 0); /* Ensure we have soft control over all registers */ regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2, From 0e36f32f6b6c4c86a6bf3d6f0940831691b0a3b0 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Wed, 13 May 2020 09:28:07 -0500 Subject: [PATCH 246/428] ASoC: tlv320adcx140: Fix bias config values The device tree binding declares the ti,mic-bias-source and the ti,vref-source properties as u32. The code reads them as u8 which is incorrect. Since the device tree binding indicates them as u32 the conde needs to be updated to read u32. In addition the bias source needs to be shifted 4 bits to correctly write the register. driver family") Fixes: 37bde5acf040 ("ASoC: tlv320adcx140: Add the tlv320adcx140 codec Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200513142807.11802-1-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 13 +++++++------ sound/soc/codecs/tlv320adcx140.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 0f713efde046..1d7d7b34a46e 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -739,11 +739,12 @@ static int adcx140_codec_probe(struct snd_soc_component *component) { struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); int sleep_cfg_val = ADCX140_WAKE_DEV; - u8 bias_source; - u8 vref_source; + u32 bias_source; + u32 vref_source; + u8 bias_cfg; int ret; - ret = device_property_read_u8(adcx140->dev, "ti,mic-bias-source", + ret = device_property_read_u32(adcx140->dev, "ti,mic-bias-source", &bias_source); if (ret) bias_source = ADCX140_MIC_BIAS_VAL_VREF; @@ -754,7 +755,7 @@ static int adcx140_codec_probe(struct snd_soc_component *component) return -EINVAL; } - ret = device_property_read_u8(adcx140->dev, "ti,vref-source", + ret = device_property_read_u32(adcx140->dev, "ti,vref-source", &vref_source); if (ret) vref_source = ADCX140_MIC_BIAS_VREF_275V; @@ -765,7 +766,7 @@ static int adcx140_codec_probe(struct snd_soc_component *component) return -EINVAL; } - bias_source |= vref_source; + bias_cfg = bias_source << ADCX140_MIC_BIAS_SHIFT | vref_source; ret = adcx140_reset(adcx140); if (ret) @@ -785,7 +786,7 @@ static int adcx140_codec_probe(struct snd_soc_component *component) ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG, ADCX140_MIC_BIAS_VAL_MSK | - ADCX140_MIC_BIAS_VREF_MSK, bias_source); + ADCX140_MIC_BIAS_VREF_MSK, bias_cfg); if (ret) dev_err(adcx140->dev, "setting MIC bias failed %d\n", ret); out: diff --git a/sound/soc/codecs/tlv320adcx140.h b/sound/soc/codecs/tlv320adcx140.h index 6d055e55909e..69de52d473f4 100644 --- a/sound/soc/codecs/tlv320adcx140.h +++ b/sound/soc/codecs/tlv320adcx140.h @@ -116,6 +116,7 @@ #define ADCX140_MIC_BIAS_VAL_VREF_1096 1 #define ADCX140_MIC_BIAS_VAL_AVDD 6 #define ADCX140_MIC_BIAS_VAL_MSK GENMASK(6, 4) +#define ADCX140_MIC_BIAS_SHIFT 4 #define ADCX140_MIC_BIAS_VREF_275V 0 #define ADCX140_MIC_BIAS_VREF_25V 1 From 7cfa610205d95357f9eface292dc70fce7571f65 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 14 May 2020 07:33:36 -0500 Subject: [PATCH 247/428] ASoC: tlv320adcx140: Add controls for PDM clk Add ALSA controls to configure the PDM clocks. The clocks need to be configurable to accommodate various microphones that use clocks for low power/low resolution modes to high power/high resolution modes. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200514123338.20392-1-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 0f713efde046..97634e0ca0ba 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -180,6 +180,17 @@ static const struct snd_kcontrol_new decimation_filter_controls[] = { SOC_DAPM_ENUM("Decimation Filter", decimation_filter_enum), }; +static const char * const pdmclk_text[] = { + "2.8224 MHz", "1.4112 MHz", "705.6 kHz", "5.6448 MHz" +}; + +static SOC_ENUM_SINGLE_DECL(pdmclk_select_enum, ADCX140_PDMCLK_CFG, 0, + pdmclk_text); + +static const struct snd_kcontrol_new pdmclk_div_controls[] = { + SOC_DAPM_ENUM("PDM Clk Divider Select", pdmclk_select_enum), +}; + static const char * const resistor_text[] = { "2.5 kOhm", "10 kOhm", "20 kOhm" }; @@ -416,6 +427,9 @@ static const struct snd_soc_dapm_widget adcx140_dapm_widgets[] = { SND_SOC_DAPM_MUX("IN4 Analog Mic Resistor", SND_SOC_NOPM, 0, 0, in4_resistor_controls), + SND_SOC_DAPM_MUX("PDM Clk Div Select", SND_SOC_NOPM, 0, 0, + pdmclk_div_controls), + SND_SOC_DAPM_MUX("Decimation Filter", SND_SOC_NOPM, 0, 0, decimation_filter_controls), }; @@ -493,6 +507,11 @@ static const struct snd_soc_dapm_route adcx140_audio_map[] = { {"IN4 Analog Mic Resistor", "10 kOhm", "MIC4M Input Mux"}, {"IN4 Analog Mic Resistor", "20 kOhm", "MIC4M Input Mux"}, + {"PDM Clk Div Select", "2.8224 MHz", "MIC1P Input Mux"}, + {"PDM Clk Div Select", "1.4112 MHz", "MIC1P Input Mux"}, + {"PDM Clk Div Select", "705.6 kHz", "MIC1P Input Mux"}, + {"PDM Clk Div Select", "5.6448 MHz", "MIC1P Input Mux"}, + {"MIC1 Analog Mux", "Line In", "MIC1P"}, {"MIC2 Analog Mux", "Line In", "MIC2P"}, {"MIC3 Analog Mux", "Line In", "MIC3P"}, From 75b0adbb0806a141b0b5f074cd6bd58bb9870c0d Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 14 May 2020 07:33:37 -0500 Subject: [PATCH 248/428] ASoC: tlv320adcx140: Add device tree property for PDM edges Add a device tree property to configure the PDM sampling edge for each digital microphone. Signed-off-by: Dan Murphy CC: Rob Herring Link: https://lore.kernel.org/r/20200514123338.20392-2-dmurphy@ti.com Signed-off-by: Mark Brown --- .../bindings/sound/tlv320adcx140.yaml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml index ab2268c0ee67..daa6cc0e031b 100644 --- a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml +++ b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml @@ -63,6 +63,29 @@ properties: - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1, 2] + ti,pdm-edge-select: + description: | + Defines the PDMCLK sampling edge configuration for the PDM inputs. This + array is defined as . + + 0 - (default) Odd channel is latched on the negative edge and even + channel is latched on the the positive edge. + 1 - Odd channel is latched on the positive edge and even channel is + latched on the the negative edge. + + PDMIN1 - PDMCLK latching edge used for channel 1 and 2 data + PDMIN2 - PDMCLK latching edge used for channel 3 and 4 data + PDMIN3 - PDMCLK latching edge used for channel 5 and 6 data + PDMIN4 - PDMCLK latching edge used for channel 7 and 8 data + + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-array + - minItems: 1 + maxItems: 4 + items: + maximum: 1 + default: [0, 0, 0, 0] + required: - compatible - reg @@ -77,6 +100,7 @@ examples: compatible = "ti,tlv320adc5140"; reg = <0x4c>; ti,mic-bias-source = <6>; + ti,pdm-edge-select = <0 1 0 1>; reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; }; }; From 79fc48e41e39d7a98c5f8ae37f613d7ff9953c86 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 14 May 2020 07:33:38 -0500 Subject: [PATCH 249/428] ASoC: tlv320adcx140: Configure PDM sampling edge Configure the PDM sampling edges based on the values from the firmware. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200514123338.20392-3-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 22 ++++++++++++++++++++++ sound/soc/codecs/tlv320adcx140.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 97634e0ca0ba..140a5802a9a9 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -760,6 +760,10 @@ static int adcx140_codec_probe(struct snd_soc_component *component) int sleep_cfg_val = ADCX140_WAKE_DEV; u8 bias_source; u8 vref_source; + int pdm_count; + u32 pdm_edges[ADCX140_NUM_PDM_EDGES]; + u32 pdm_edge_val = 0; + int i; int ret; ret = device_property_read_u8(adcx140->dev, "ti,mic-bias-source", @@ -786,6 +790,24 @@ static int adcx140_codec_probe(struct snd_soc_component *component) bias_source |= vref_source; + pdm_count = device_property_count_u32(adcx140->dev, + "ti,pdm-edge-select"); + if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) { + ret = device_property_read_u32_array(adcx140->dev, + "ti,pdm-edge-select", + pdm_edges, pdm_count); + if (ret) + return ret; + + for (i = 0; i < pdm_count; i++) + pdm_edge_val |= pdm_edges[i] << (ADCX140_PDM_EDGE_SHIFT - i); + + ret = regmap_write(adcx140->regmap, ADCX140_PDM_CFG, + pdm_edge_val); + if (ret) + return ret; + } + ret = adcx140_reset(adcx140); if (ret) goto out; diff --git a/sound/soc/codecs/tlv320adcx140.h b/sound/soc/codecs/tlv320adcx140.h index 6d055e55909e..432eaf25d1a7 100644 --- a/sound/soc/codecs/tlv320adcx140.h +++ b/sound/soc/codecs/tlv320adcx140.h @@ -128,4 +128,7 @@ #define ADCX140_TX_OFFSET_MASK GENMASK(4, 0) +#define ADCX140_NUM_PDM_EDGES 4 +#define ADCX140_PDM_EDGE_SHIFT 7 + #endif /* _TLV320ADCX140_ */ From 6878e75204e1d0420fd8130bad33f88053ba44de Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 15 May 2020 18:10:50 +0800 Subject: [PATCH 250/428] ASoC: fsl_esai: introduce SoC specific data Introduce a SoC specific data structure which contains the differences between the different SoCs. This makes it easier to support more differences without having to introduce a new if/else each time. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/c188279975bd216995904f9bf8a84c7887b759a0.1589537601.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 46 ++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 84290be778f0..bac65ba7fbad 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -21,6 +21,17 @@ SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE) +/** + * fsl_esai_soc_data: soc specific data + * + * @imx: for imx platform + * @reset_at_xrun: flags for enable reset operaton + */ +struct fsl_esai_soc_data { + bool imx; + bool reset_at_xrun; +}; + /** * fsl_esai: ESAI private data * @@ -33,6 +44,7 @@ * @fsysclk: system clock source to derive HCK, SCK and FS * @spbaclk: SPBA clock (optional, depending on SoC design) * @task: tasklet to handle the reset operation + * @soc: soc specific data * @lock: spin lock between hw_reset() and trigger() * @fifo_depth: depth of tx/rx FIFO * @slot_width: width of each DAI slot @@ -44,7 +56,6 @@ * @sck_div: if using PSR/PM dividers for SCKx clock * @slave_mode: if fully using DAI slave mode * @synchronous: if using tx/rx synchronous mode - * @reset_at_xrun: flags for enable reset operaton * @name: driver name */ struct fsl_esai { @@ -57,6 +68,7 @@ struct fsl_esai { struct clk *fsysclk; struct clk *spbaclk; struct tasklet_struct task; + const struct fsl_esai_soc_data *soc; spinlock_t lock; /* Protect hw_reset and trigger */ u32 fifo_depth; u32 slot_width; @@ -70,10 +82,24 @@ struct fsl_esai { bool sck_div[2]; bool slave_mode; bool synchronous; - bool reset_at_xrun; char name[32]; }; +static struct fsl_esai_soc_data fsl_esai_vf610 = { + .imx = false, + .reset_at_xrun = true, +}; + +static struct fsl_esai_soc_data fsl_esai_imx35 = { + .imx = true, + .reset_at_xrun = true, +}; + +static struct fsl_esai_soc_data fsl_esai_imx6ull = { + .imx = true, + .reset_at_xrun = false, +}; + static irqreturn_t esai_isr(int irq, void *devid) { struct fsl_esai *esai_priv = (struct fsl_esai *)devid; @@ -85,7 +111,7 @@ static irqreturn_t esai_isr(int irq, void *devid) regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr); if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) && - esai_priv->reset_at_xrun) { + esai_priv->soc->reset_at_xrun) { dev_dbg(&pdev->dev, "reset module for xrun\n"); regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, ESAI_xCR_xEIE_MASK, 0); @@ -936,9 +962,11 @@ static int fsl_esai_probe(struct platform_device *pdev) esai_priv->pdev = pdev; snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np); - if (of_device_is_compatible(np, "fsl,vf610-esai") || - of_device_is_compatible(np, "fsl,imx35-esai")) - esai_priv->reset_at_xrun = true; + esai_priv->soc = of_device_get_match_data(&pdev->dev); + if (!esai_priv->soc) { + dev_err(&pdev->dev, "failed to get soc data\n"); + return -ENODEV; + } /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1063,9 +1091,9 @@ static int fsl_esai_remove(struct platform_device *pdev) } static const struct of_device_id fsl_esai_dt_ids[] = { - { .compatible = "fsl,imx35-esai", }, - { .compatible = "fsl,vf610-esai", }, - { .compatible = "fsl,imx6ull-esai", }, + { .compatible = "fsl,imx35-esai", .data = &fsl_esai_imx35 }, + { .compatible = "fsl,vf610-esai", .data = &fsl_esai_vf610 }, + { .compatible = "fsl,imx6ull-esai", .data = &fsl_esai_imx6ull }, {} }; MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); From d59628b310a77e616ce2e5857e6ede5bf96c6784 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 15 May 2020 18:10:51 +0800 Subject: [PATCH 251/428] ASoC: fsl_esai: Add new compatible string for imx8qm Add new compatible string "fsl,imx8qm-esai" in the binding document. Signed-off-by: Shengjiu Wang Acked-by: Rob Herring Link: https://lore.kernel.org/r/fade597f6fb7e0ef9eb1185b491eaa46a9d287e3.1589537601.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,esai.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index 0e6e2166f76c..0a2480aeecf0 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt @@ -12,6 +12,7 @@ Required properties: "fsl,imx35-esai", "fsl,vf610-esai", "fsl,imx6ull-esai", + "fsl,imx8qm-esai", - reg : Offset and length of the register set for the device. From 93fa0af4790abdabf80ca0c4fff3f1629c84a56f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 15 May 2020 12:03:09 +0200 Subject: [PATCH 252/428] ASoC: cros_ec_codec: switch to library API for SHA-256 The CrOS EC codec driver uses SHA-256 explicitly, and not in a performance critical manner, so there is really no point in using the SHASH crypto API here. Let's switch to the library API instead. Signed-off-by: Ard Biesheuvel Reviewed-by: Tzung-Bi Shih Cc: Cheng-Yi Chiang Cc: Enric Balletbo i Serra Cc: Guenter Roeck Cc: Benson Leung Cc: Liam Girdwood Cc: Mark Brown Cc: Arnd Bergmann Cc: Eric Biggers Cc: Herbert Xu Cc: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200515100309.20795-1-ardb@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 3 +-- sound/soc/codecs/cros_ec_codec.c | 23 ++++------------------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 44b8c4cde4f3..2d4f1b4bc011 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -538,8 +538,7 @@ config SND_SOC_CQ0093VC config SND_SOC_CROS_EC_CODEC tristate "codec driver for ChromeOS EC" depends on CROS_EC - select CRYPTO - select CRYPTO_SHA256 + select CRYPTO_LIB_SHA256 help If you say yes here you will get support for the ChromeOS Embedded Controller's Audio Codec. diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index 1948bc6971f6..8d45c628e988 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -8,7 +8,6 @@ * EC for audio function. */ -#include #include #include #include @@ -107,25 +106,11 @@ error: static int calculate_sha256(struct cros_ec_codec_priv *priv, uint8_t *buf, uint32_t size, uint8_t *digest) { - struct crypto_shash *tfm; - struct shash_desc *desc; + struct sha256_state sctx; - tfm = crypto_alloc_shash("sha256", CRYPTO_ALG_TYPE_SHASH, 0); - if (IS_ERR(tfm)) { - dev_err(priv->dev, "can't alloc shash\n"); - return PTR_ERR(tfm); - } - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); - if (!desc) { - crypto_free_shash(tfm); - return -ENOMEM; - } - desc->tfm = tfm; - crypto_shash_digest(desc, buf, size, digest); - shash_desc_zero(desc); - - kfree(desc); - crypto_free_shash(tfm); + sha256_init(&sctx); + sha256_update(&sctx, buf, size); + sha256_final(&sctx, digest); #ifdef DEBUG { From 47b4f5f5b65680fbef7a7a9a4796b35f38a6e43e Mon Sep 17 00:00:00 2001 From: Thomas Ebeling Date: Fri, 15 May 2020 13:46:05 +0200 Subject: [PATCH 253/428] ALSA: usb-audio: fixing upper volume limit for RME Babyface Pro routing crosspoints In my initial patch, these were set too low. Fixes: 3e8f3bd04716 ("ALSA: usb-audio: RME Babyface Pro mixer patch") Signed-off-by: Thomas Ebeling Link: https://lore.kernel.org/r/20200515114556.vtspnonzvp4xp44m@bollie.ca9.eu Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index bdff8674942e..aad2683ff793 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2191,7 +2191,7 @@ static int snd_rme_controls_create(struct usb_mixer_interface *mixer) * These devices exposes a couple of DSP functions via request to EP0. * Switches are available via control registers, while routing is controlled * by controlling the volume on each possible crossing point. - * Volume control is linear, from -inf (dec. 0) to +6dB (dec. 46341) with + * Volume control is linear, from -inf (dec. 0) to +6dB (dec. 65536) with * 0dB being at dec. 32768. */ enum { @@ -2220,7 +2220,7 @@ enum { #define SND_BBFPRO_MIXER_VAL_MASK 0x3ffff #define SND_BBFPRO_MIXER_VAL_SHIFT 9 #define SND_BBFPRO_MIXER_VAL_MIN 0 // -inf -#define SND_BBFPRO_MIXER_VAL_MAX 46341 // +6dB +#define SND_BBFPRO_MIXER_VAL_MAX 65536 // +6dB #define SND_BBFPRO_USBREQ_CTL_REG1 0x10 #define SND_BBFPRO_USBREQ_CTL_REG2 0x17 From 10ce77e4817fef99e1166be7e6685a80c63bf77f Mon Sep 17 00:00:00 2001 From: Erwin Burema Date: Sun, 10 May 2020 20:29:11 +0200 Subject: [PATCH 254/428] ALSA: usb-audio: Add duplex sound support for USB devices using implicit feedback For USB sound devices using implicit feedback the endpoint used for this feedback should be able to be opened twice, once for required feedback and second time for audio data. This way these devices can be put in duplex audio mode. Since this only works if the settings of the endpoint don't change a check is included for this. This fixes bug 207023 ("MOTU M2 regression on duplex audio") and should also fix bug 103751 ("M-Audio Fast Track Ultra usb audio device will not operate full-duplex") Fixes: c249177944b6 ("ALSA: usb-audio: add implicit fb quirk for MOTU M Series") Signed-off-by: Erwin Burema BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=207023 BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=103751 Link: https://lore.kernel.org/r/2410739.SCZni40SNb@alpha-wolf Signed-off-by: Takashi Iwai --- sound/usb/card.h | 1 + sound/usb/endpoint.c | 195 ++++++++++++++++++++++++++++++++++++++++++- sound/usb/pcm.c | 5 ++ 3 files changed, 197 insertions(+), 4 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 820e564656ed..d6219fba9699 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -108,6 +108,7 @@ struct snd_usb_endpoint { int iface, altsetting; int skip_packets; /* quirks for devices to ignore the first n packets in a stream */ + bool is_implicit_feedback; /* This endpoint is used as implicit feedback */ spinlock_t lock; struct list_head list; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 50104f658ed4..9bea7d3f99f8 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -522,6 +522,8 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, list_add_tail(&ep->list, &chip->ep_list); + ep->is_implicit_feedback = 0; + __exit_unlock: mutex_unlock(&chip->mutex); @@ -621,6 +623,178 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) ep->nurbs = 0; } +/* + * Check data endpoint for format differences + */ +static bool check_ep_params(struct snd_usb_endpoint *ep, + snd_pcm_format_t pcm_format, + unsigned int channels, + unsigned int period_bytes, + unsigned int frames_per_period, + unsigned int periods_per_buffer, + struct audioformat *fmt, + struct snd_usb_endpoint *sync_ep) +{ + unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb; + unsigned int max_packs_per_period, urbs_per_period, urb_packs; + unsigned int max_urbs; + int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels; + int tx_length_quirk = (ep->chip->tx_length_quirk && + usb_pipeout(ep->pipe)); + bool ret = 1; + + if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) { + /* + * When operating in DSD DOP mode, the size of a sample frame + * in hardware differs from the actual physical format width + * because we need to make room for the DOP markers. + */ + frame_bits += channels << 3; + } + + ret = ret && (ep->datainterval == fmt->datainterval); + ret = ret && (ep->stride == frame_bits >> 3); + + switch (pcm_format) { + case SNDRV_PCM_FORMAT_U8: + ret = ret && (ep->silence_value == 0x80); + break; + case SNDRV_PCM_FORMAT_DSD_U8: + case SNDRV_PCM_FORMAT_DSD_U16_LE: + case SNDRV_PCM_FORMAT_DSD_U32_LE: + case SNDRV_PCM_FORMAT_DSD_U16_BE: + case SNDRV_PCM_FORMAT_DSD_U32_BE: + ret = ret && (ep->silence_value == 0x69); + break; + default: + ret = ret && (ep->silence_value == 0); + } + + /* assume max. frequency is 50% higher than nominal */ + ret = ret && (ep->freqmax == ep->freqn + (ep->freqn >> 1)); + /* Round up freqmax to nearest integer in order to calculate maximum + * packet size, which must represent a whole number of frames. + * This is accomplished by adding 0x0.ffff before converting the + * Q16.16 format into integer. + * In order to accurately calculate the maximum packet size when + * the data interval is more than 1 (i.e. ep->datainterval > 0), + * multiply by the data interval prior to rounding. For instance, + * a freqmax of 41 kHz will result in a max packet size of 6 (5.125) + * frames with a data interval of 1, but 11 (10.25) frames with a + * data interval of 2. + * (ep->freqmax << ep->datainterval overflows at 8.192 MHz for the + * maximum datainterval value of 3, at USB full speed, higher for + * USB high speed, noting that ep->freqmax is in units of + * frames per packet in Q16.16 format.) + */ + maxsize = (((ep->freqmax << ep->datainterval) + 0xffff) >> 16) * + (frame_bits >> 3); + if (tx_length_quirk) + maxsize += sizeof(__le32); /* Space for length descriptor */ + /* but wMaxPacketSize might reduce this */ + if (ep->maxpacksize && ep->maxpacksize < maxsize) { + /* whatever fits into a max. size packet */ + unsigned int data_maxsize = maxsize = ep->maxpacksize; + + if (tx_length_quirk) + /* Need to remove the length descriptor to calc freq */ + data_maxsize -= sizeof(__le32); + ret = ret && (ep->freqmax == (data_maxsize / (frame_bits >> 3)) + << (16 - ep->datainterval)); + } + + if (ep->fill_max) + ret = ret && (ep->curpacksize == ep->maxpacksize); + else + ret = ret && (ep->curpacksize == maxsize); + + if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) { + packs_per_ms = 8 >> ep->datainterval; + max_packs_per_urb = MAX_PACKS_HS; + } else { + packs_per_ms = 1; + max_packs_per_urb = MAX_PACKS; + } + if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep)) + max_packs_per_urb = min(max_packs_per_urb, + 1U << sync_ep->syncinterval); + max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval); + + /* + * Capture endpoints need to use small URBs because there's no way + * to tell in advance where the next period will end, and we don't + * want the next URB to complete much after the period ends. + * + * Playback endpoints with implicit sync much use the same parameters + * as their corresponding capture endpoint. + */ + if (usb_pipein(ep->pipe) || + snd_usb_endpoint_implicit_feedback_sink(ep)) { + + urb_packs = packs_per_ms; + /* + * Wireless devices can poll at a max rate of once per 4ms. + * For dataintervals less than 5, increase the packet count to + * allow the host controller to use bursting to fill in the + * gaps. + */ + if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_WIRELESS) { + int interval = ep->datainterval; + + while (interval < 5) { + urb_packs <<= 1; + ++interval; + } + } + /* make capture URBs <= 1 ms and smaller than a period */ + urb_packs = min(max_packs_per_urb, urb_packs); + while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) + urb_packs >>= 1; + ret = ret && (ep->nurbs == MAX_URBS); + + /* + * Playback endpoints without implicit sync are adjusted so that + * a period fits as evenly as possible in the smallest number of + * URBs. The total number of URBs is adjusted to the size of the + * ALSA buffer, subject to the MAX_URBS and MAX_QUEUE limits. + */ + } else { + /* determine how small a packet can be */ + minsize = (ep->freqn >> (16 - ep->datainterval)) * + (frame_bits >> 3); + /* with sync from device, assume it can be 12% lower */ + if (sync_ep) + minsize -= minsize >> 3; + minsize = max(minsize, 1u); + + /* how many packets will contain an entire ALSA period? */ + max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize); + + /* how many URBs will contain a period? */ + urbs_per_period = DIV_ROUND_UP(max_packs_per_period, + max_packs_per_urb); + /* how many packets are needed in each URB? */ + urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period); + + /* limit the number of frames in a single URB */ + ret = ret && (ep->max_urb_frames == + DIV_ROUND_UP(frames_per_period, urbs_per_period)); + + /* try to use enough URBs to contain an entire ALSA buffer */ + max_urbs = min((unsigned) MAX_URBS, + MAX_QUEUE * packs_per_ms / urb_packs); + ret = ret && (ep->nurbs == min(max_urbs, + urbs_per_period * periods_per_buffer)); + } + + ret = ret && (ep->datainterval == fmt->datainterval); + ret = ret && (ep->maxpacksize == fmt->maxpacksize); + ret = ret && + (ep->fill_max == !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX)); + + return ret; +} + /* * configure a data endpoint */ @@ -886,10 +1060,23 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, int err; if (ep->use_count != 0) { - usb_audio_warn(ep->chip, - "Unable to change format on ep #%x: already in use\n", - ep->ep_num); - return -EBUSY; + bool check = ep->is_implicit_feedback && + check_ep_params(ep, pcm_format, + channels, period_bytes, + period_frames, buffer_periods, + fmt, sync_ep); + + if (!check) { + usb_audio_warn(ep->chip, + "Unable to change format on ep #%x: already in use\n", + ep->ep_num); + return -EBUSY; + } + + usb_audio_dbg(ep->chip, + "Ep #%x already in use as implicit feedback but format not changed\n", + ep->ep_num); + return 0; } /* release old buffers, if any */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index b50965ab3b3a..d61c2f1095b5 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -404,6 +404,8 @@ add_sync_ep: if (!subs->sync_endpoint) return -EINVAL; + subs->sync_endpoint->is_implicit_feedback = 1; + subs->data_endpoint->sync_master = subs->sync_endpoint; return 1; @@ -502,12 +504,15 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, implicit_fb ? SND_USB_ENDPOINT_TYPE_DATA : SND_USB_ENDPOINT_TYPE_SYNC); + if (!subs->sync_endpoint) { if (is_playback && attr == USB_ENDPOINT_SYNC_NONE) return 0; return -EINVAL; } + subs->sync_endpoint->is_implicit_feedback = implicit_fb; + subs->data_endpoint->sync_master = subs->sync_endpoint; return 0; From c637fa151259c0f74665fde7cba5b7eac1417ae5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 16 May 2020 08:25:56 +0200 Subject: [PATCH 255/428] ALSA: hda: Fix potential race in unsol event handler The unsol event handling code has a loop retrieving the read/write indices and the arrays without locking while the append to the array may happen concurrently. This may lead to some inconsistency. Although there hasn't been any proof of this bad results, it's still safer to protect the racy accesses. This patch adds the spinlock protection around the unsol handling loop for addressing it. Here we take bus->reg_lock as the writer side snd_hdac_bus_queue_event() is also protected by that lock. Link: https://lore.kernel.org/r/20200516062556.30951-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/hda/hdac_bus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 3fe62be1cbcc..dee04792ca86 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -162,6 +162,7 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work) struct hdac_driver *drv; unsigned int rp, caddr, res; + spin_lock_irq(&bus->reg_lock); while (bus->unsol_rp != bus->unsol_wp) { rp = (bus->unsol_rp + 1) % HDA_UNSOL_QUEUE_SIZE; bus->unsol_rp = rp; @@ -173,10 +174,13 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work) codec = bus->caddr_tbl[caddr & 0x0f]; if (!codec || !codec->dev.driver) continue; + spin_unlock_irq(&bus->reg_lock); drv = drv_to_hdac_driver(codec->dev.driver); if (drv->unsol_event) drv->unsol_event(codec, res); + spin_lock_irq(&bus->reg_lock); } + spin_unlock_irq(&bus->reg_lock); } /** From 6325c7fade7db4d6ebefd44604176476ffad6a4b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 16 May 2020 08:28:53 +0200 Subject: [PATCH 256/428] ALSA: hda: Drop unused snd_hda_queue_unsol_event() The inline function is nowhere used. Drop it. Link: https://lore.kernel.org/r/20200516062854.22141-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- include/sound/hda_codec.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 8a32060e3d8d..d16a4229209b 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -366,13 +366,6 @@ struct hda_verb { void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq); -/* unsolicited event */ -static inline void -snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) -{ - snd_hdac_bus_queue_event(&bus->core, res, res_ex); -} - /* cached write */ static inline int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, From b9f2d35f05308813c4c887d5c530004f01e1829c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 16 May 2020 08:28:54 +0200 Subject: [PATCH 257/428] ALSA: hda: Unexport some local helper functions snd_hdac_bus_queue_event() and snd_hdac_bus_exec_verb() are used only internally in HD-audio core. Let's drop the exports and move the declarations into local.h. Link: https://lore.kernel.org/r/20200516062854.22141-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 3 --- sound/hda/hdac_bus.c | 2 -- sound/hda/hdac_controller.c | 1 + sound/hda/local.h | 3 +++ 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 10945963d727..c1f78d9a6e47 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -372,11 +372,8 @@ struct hdac_bus { int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops); void snd_hdac_bus_exit(struct hdac_bus *bus); -int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, - unsigned int cmd, unsigned int *res); int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, unsigned int cmd, unsigned int *res); -void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); static inline void snd_hdac_codec_link_up(struct hdac_device *codec) { diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index dee04792ca86..09ddab5f5cae 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -81,7 +81,6 @@ int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, mutex_unlock(&bus->cmd_mutex); return err; } -EXPORT_SYMBOL_GPL(snd_hdac_bus_exec_verb); /** * snd_hdac_bus_exec_verb_unlocked - unlocked version @@ -150,7 +149,6 @@ void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex) schedule_work(&bus->unsol_work); } -EXPORT_SYMBOL_GPL(snd_hdac_bus_queue_event); /* * process queued unsolicited events diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index ac15aa357fbd..011b17cc1efa 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -9,6 +9,7 @@ #include #include #include +#include "local.h" /* clear CORB read pointer properly */ static void azx_clear_corbrp(struct hdac_bus *bus) diff --git a/sound/hda/local.h b/sound/hda/local.h index 5b935219352f..896ba142e8bc 100644 --- a/sound/hda/local.h +++ b/sound/hda/local.h @@ -36,6 +36,9 @@ void hda_widget_sysfs_exit(struct hdac_device *codec); int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec); void snd_hdac_bus_remove_device(struct hdac_bus *bus, struct hdac_device *codec); +void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); +int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, + unsigned int cmd, unsigned int *res); int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, unsigned int flags, unsigned int *res); From b5dff6ec13260585164d4cd13d7a3ec79bd26acb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:15:29 -0500 Subject: [PATCH 258/428] ASoC: codecs: rt*-sdw: don't assign slave_ops The SoundWire bus core already assigns the slave ops, no need to set them a second time manually in each driver. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Rander Wang Cc: Oder Chiou Cc: Shuming Fan Cc: Jack Yu Link: https://lore.kernel.org/r/20200515211531.11416-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 3 --- sound/soc/codecs/rt5682-sdw.c | 3 --- sound/soc/codecs/rt700-sdw.c | 3 --- sound/soc/codecs/rt711-sdw.c | 3 --- sound/soc/codecs/rt715-sdw.c | 3 --- 5 files changed, 15 deletions(-) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 1502a22b0d4a..4b88fa8efb27 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -684,9 +684,6 @@ static int rt1308_sdw_probe(struct sdw_slave *slave, { struct regmap *regmap; - /* Assign ops */ - slave->ops = &rt1308_slave_ops; - /* Regmap Initialization */ regmap = devm_regmap_init_sdw(slave, &rt1308_sdw_regmap); if (!regmap) diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index a2d1d3ae1e31..99dd48d2a1d6 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -241,9 +241,6 @@ static int rt5682_sdw_probe(struct sdw_slave *slave, { struct regmap *regmap; - /* Assign ops */ - slave->ops = &rt5682_slave_ops; - /* Regmap Initialization */ regmap = devm_regmap_init_sdw(slave, &rt5682_sdw_regmap); if (IS_ERR(regmap)) diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index d4e0f953bcce..4d14048d1197 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -450,9 +450,6 @@ static int rt700_sdw_probe(struct sdw_slave *slave, { struct regmap *sdw_regmap, *regmap; - /* Assign ops */ - slave->ops = &rt700_slave_ops; - /* Regmap Initialization */ sdw_regmap = devm_regmap_init_sdw(slave, &rt700_sdw_regmap); if (!sdw_regmap) diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index fc3a3fa3d51b..45b928954b58 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -450,9 +450,6 @@ static int rt711_sdw_probe(struct sdw_slave *slave, { struct regmap *sdw_regmap, *regmap; - /* Assign ops */ - slave->ops = &rt711_slave_ops; - /* Regmap Initialization */ sdw_regmap = devm_regmap_init_sdw(slave, &rt711_sdw_regmap); if (!sdw_regmap) diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 64ef56ef0318..d11b23d6b240 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -525,9 +525,6 @@ static int rt715_sdw_probe(struct sdw_slave *slave, { struct regmap *sdw_regmap, *regmap; - /* Assign ops */ - slave->ops = &rt715_slave_ops; - /* Regmap Initialization */ sdw_regmap = devm_regmap_init_sdw(slave, &rt715_sdw_regmap); if (!sdw_regmap) From 07b542fe831cbefce163ad1b3aa7292c8a6332b8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:15:30 -0500 Subject: [PATCH 259/428] ASoC: codecs: rt*-sdw: fix memory leak in set_sdw_stream() Now that the sdw_stream is allocated in machine driver, set_sdw_stream() is also called with a NULL argument during the dailink shutdown. In this case, the drivers should not allocate any memory, and just return. Detected with KASAN/kmemleak. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Rander Wang Cc: Oder Chiou Cc: Shuming Fan Cc: Jack Yu Link: https://lore.kernel.org/r/20200515211531.11416-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 3 +++ sound/soc/codecs/rt5682.c | 3 +++ sound/soc/codecs/rt700.c | 3 +++ sound/soc/codecs/rt711.c | 3 +++ sound/soc/codecs/rt715.c | 3 +++ 5 files changed, 15 insertions(+) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 4b88fa8efb27..91cc5a15c211 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -482,6 +482,9 @@ static int rt1308_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, { struct sdw_stream_data *stream; + if (!sdw_stream) + return 0; + stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (!stream) return -ENOMEM; diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 5d3b11756a34..046e6110de73 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2935,6 +2935,9 @@ static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, { struct sdw_stream_data *stream; + if (!sdw_stream) + return 0; + stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (!stream) return -ENOMEM; diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index ff68f0e4f629..687ac2153666 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -860,6 +860,9 @@ static int rt700_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, { struct sdw_stream_data *stream; + if (!sdw_stream) + return 0; + stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (!stream) return -ENOMEM; diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 2daed7692a3b..65b59dbfb43c 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -906,6 +906,9 @@ static int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, { struct sdw_stream_data *stream; + if (!sdw_stream) + return 0; + stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (!stream) return -ENOMEM; diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index 2cbc57b16b13..099c8bd20006 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -530,6 +530,9 @@ static int rt715_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, struct sdw_stream_data *stream; + if (!sdw_stream) + return 0; + stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (!stream) return -ENOMEM; From ee5866222ab58531c988492ea54931c1346d4fd4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:15:31 -0500 Subject: [PATCH 260/428] ASoC: codecs: rt1308-sdw: remove duplicate allocation The .read_prop callback is supposed to be called by the SoundWire core only. Calling it again from this driver results in an additional memory allocation for no good reason. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Rander Wang Cc: Oder Chiou Cc: Shuming Fan Cc: Jack Yu Link: https://lore.kernel.org/r/20200515211531.11416-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 91cc5a15c211..b0ba0d2acbdd 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -178,10 +178,6 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave) if (rt1308->hw_init) return 0; - ret = rt1308_read_prop(slave); - if (ret < 0) - goto _io_init_err_; - if (rt1308->first_hw_init) { regcache_cache_only(rt1308->regmap, false); regcache_cache_bypass(rt1308->regmap, true); @@ -282,7 +278,6 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave) dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); -_io_init_err_: return ret; } From c26fde3b15ed41f5f452f1da727795f787833287 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 15 May 2020 16:59:51 +0300 Subject: [PATCH 261/428] ASoC: SOF: Do nothing when DSP PM callbacks are not set This provides a better separation between runtime and PM sleep callbacks. Only do nothing if given runtime flag is set and calback is not set. With the current implementation, if PM sleep callback is set but runtime callback is not set then at runtime resume we reload the firmware even if we do not support runtime resume callback. Signed-off-by: Daniel Baluta Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200515135958.17511-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 1f8f7e33979d..119e4d644ef4 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -90,7 +90,10 @@ static int sof_resume(struct device *dev, bool runtime_resume) int ret; /* do nothing if dsp resume callbacks are not set */ - if (!sof_ops(sdev)->resume || !sof_ops(sdev)->runtime_resume) + if (!runtime_resume && !sof_ops(sdev)->resume) + return 0; + + if (runtime_resume && !sof_ops(sdev)->runtime_resume) return 0; /* DSP was never successfully started, nothing to resume */ @@ -175,7 +178,10 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) int ret; /* do nothing if dsp suspend callback is not set */ - if (!sof_ops(sdev)->suspend) + if (!runtime_suspend && !sof_ops(sdev)->suspend) + return 0; + + if (runtime_suspend && !sof_ops(sdev)->runtime_suspend) return 0; if (sdev->fw_state != SOF_FW_BOOT_COMPLETE) From 3541aef1b83fa3a13e9c4ecc0919156ff2ec9c22 Mon Sep 17 00:00:00 2001 From: Marcin Rajwa Date: Fri, 15 May 2020 16:59:52 +0300 Subject: [PATCH 262/428] ASoC: SOF: add a power_down_notify method This patch adds a snd_sof_dsp_power_down_notify() method which aims to prepare the DSP for the upcoming power down. This new function make use of SOF_IPC_PM_CTX_SAVE message. Signed-off-by: Marcin Rajwa Signed-off-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200515135958.17511-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 9 +++++++++ sound/soc/sof/sof-priv.h | 1 + 2 files changed, 10 insertions(+) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 119e4d644ef4..5e804a7728f5 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -256,6 +256,15 @@ suspend: return ret; } +int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev) +{ + /* Notify DSP of upcoming power down */ + if (sof_ops(sdev)->remove) + return sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_SAVE); + + return 0; +} + int snd_sof_runtime_suspend(struct device *dev) { return sof_suspend(dev, true); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index a34dbae9f971..3ed39b887214 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -453,6 +453,7 @@ 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); +int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev); int snd_sof_prepare(struct device *dev); void snd_sof_complete(struct device *dev); From 9f369f7e4660d05b5318aa413db199a70dfb2c4f Mon Sep 17 00:00:00 2001 From: Marcin Rajwa Date: Fri, 15 May 2020 16:59:53 +0300 Subject: [PATCH 263/428] ASoC: SOF: inform DSP that driver is going to be removed This patch invokes the DSP power down notifier to inform DSP that driver is going to be removed. The module removal entails DSP power down, disabling of IRQs and more. Therefore it is highly recommended to inform the DSP about this upcoming event. Due to hardware limitations on some Intel platforms it is necessary to power gate all LPSRAM banks that were enabled prior to controller reset. Otherwise, an attempt to write LPSRAM control registers may have no effect. Signed-off-by: Marcin Rajwa Signed-off-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200515135958.17511-4-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index ef9be4f45e27..339c4930b0c0 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -343,6 +343,12 @@ int snd_sof_device_remove(struct device *dev) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct snd_sof_pdata *pdata = sdev->pdata; + int ret; + + ret = snd_sof_dsp_power_down_notify(sdev); + if (ret < 0) + dev_warn(dev, "error: %d failed to prepare DSP for device removal", + ret); if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) cancel_work_sync(&sdev->probe_work); From 82e8c00fa18a3ef0ad3087dcad1d82637a738e30 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 15 May 2020 16:59:54 +0300 Subject: [PATCH 264/428] ASoC: SOF: topology: add support to smart amplifier Add smart amplifier component support, which is designed as another new type of process component and used for speaker protection algorithm integration. Signed-off-by: Keyon Jie Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200515135958.17511-5-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 2 ++ sound/soc/sof/topology.c | 1 + 2 files changed, 3 insertions(+) diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 872de52b3144..f56e80d09b32 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -38,6 +38,7 @@ enum sof_comp_type { SOF_COMP_DEMUX, SOF_COMP_ASRC, /**< Asynchronous sample rate converter */ SOF_COMP_DCBLOCK, + SOF_COMP_SMART_AMP, /**< smart amplifier component */ /* 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 */ @@ -220,6 +221,7 @@ enum sof_ipc_process_type { SOF_PROCESS_MUX, SOF_PROCESS_DEMUX, SOF_PROCESS_DCBLOCK, + SOF_PROCESS_SMART_AMP, /**< Smart Amplifier */ }; /* generic "effect", "codec" or proprietary processing component */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 0259537d3740..6a9703e5ff60 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -431,6 +431,7 @@ static const struct sof_process_types sof_process[] = { {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, {"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK}, + {"SMART_AMP", SOF_PROCESS_SMART_AMP, SOF_COMP_SMART_AMP}, }; static enum sof_ipc_process_type find_process(const char *name) From 7d1952bceb8a1a2372a1cb86ab109c6ec8772c5c Mon Sep 17 00:00:00 2001 From: randerwang Date: Fri, 15 May 2020 16:59:55 +0300 Subject: [PATCH 265/428] ASoC: SOF: Intel: sdw: relax sdw machine select constraints On some platforms such as Up Extreme all links are enabled but only one link can be used by external codec. Instead of exact match of two masks, first check whether link_mask of mach is subset of link_mask supported by hw and then go on searching link_adr. Signed-off-by: randerwang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200515135958.17511-6-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 578ac7b036b0..63ca920c8e6e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1107,7 +1107,15 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) if (link_mask && !pdata->machine) { for (mach = pdata->desc->alt_machines; mach && mach->link_mask; mach++) { - if (mach->link_mask != link_mask) + /* + * On some platforms such as Up Extreme all links + * are enabled but only one link can be used by + * external codec. Instead of exact match of two masks, + * first check whether link_mask of mach is subset of + * link_mask supported by hw and then go on searching + * link_adr + */ + if (~link_mask & mach->link_mask) continue; /* No need to match adr if there is no links defined */ From 5c2c3cb1ca7875a2685c8cc65f08a1238e00cedb Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 15 May 2020 16:59:56 +0300 Subject: [PATCH 266/428] ASoC: SOF: define INFO_ flags in dsp_ops In the past, the INFO_ flags such as PAUSE/NO_PERIOD_WAKEUP were defined in the SOF PCM core, but that was changed since commit 27e322fabd508b ("ASoC: SOF: define INFO_ flags in dsp_ops") Now these flags must be set in DSP ops. Signed-off-by: Daniel Baluta Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200515135958.17511-7-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8m.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 3ac0444dca93..f83581041cf3 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -273,6 +273,12 @@ struct snd_sof_dsp_ops sof_imx8m_ops = { /* DAI drivers */ .drv = imx8m_dai, .num_drv = 1, /* we have only 1 SAI interface on i.MX8M */ + + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_imx8m_ops); From 35e7c09d1edd6c60bfa98070b657986500819fd6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:59:57 +0300 Subject: [PATCH 267/428] ASoC: SOF: imx: make dsp_ops static This was in the SOF tree but lost in upstream contributions Fixes: 202acc565a1f05 ("ASoC: SOF: imx: Add i.MX8 HW support") Signed-off-by: Pierre-Louis Bossart Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200515135958.17511-8-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 68b2edccd791..63f9c20a1bac 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -119,7 +119,7 @@ static void imx8_dsp_handle_request(struct imx_dsp_ipc *ipc) snd_sof_ipc_msgs_rx(priv->sdev); } -struct imx_dsp_ops dsp_ops = { +static struct imx_dsp_ops dsp_ops = { .handle_reply = imx8_dsp_handle_reply, .handle_request = imx8_dsp_handle_request, }; From 99cb681e7b8eec917ddb34b76e303aa20b2d1c1a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:59:58 +0300 Subject: [PATCH 268/428] ASoC: SOF: imx: make imx8m_dsp_ops static This was in the SOF tree but lost in upstream contributions. Fixes: afb93d716533dd ("ASoC: SOF: imx: Add i.MX8M HW support") Signed-off-by: Pierre-Louis Bossart Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200515135958.17511-9-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index f83581041cf3..fa86a9e2990f 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -92,7 +92,7 @@ static void imx8m_dsp_handle_request(struct imx_dsp_ipc *ipc) snd_sof_ipc_msgs_rx(priv->sdev); } -struct imx_dsp_ops imx8m_dsp_ops = { +static struct imx_dsp_ops imx8m_dsp_ops = { .handle_reply = imx8m_dsp_handle_reply, .handle_request = imx8m_dsp_handle_request, }; From 75ac6dce7f03b0714ee5809ff18c4d2bb2db85e0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:07:27 -0500 Subject: [PATCH 269/428] ASoC: Intel: soc-acpi: change machine driver name for WM8804 platforms Remove obsolete reference to Broxton since the machine driver will be reused on other platforms, e.g. Up Extreme. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200515210731.10942-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-bxt-match.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c index 68758e7a16d8..32f77e29c2ff 100644 --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c @@ -71,7 +71,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = { }, { .id = "1AEC8804", - .drv_name = "bxt-wm8804", + .drv_name = "sof-wm8804", .sof_fw_filename = "sof-apl.ri", .sof_tplg_filename = "sof-apl-wm8804.tplg", }, From 9d05a1e50c012368a133152515ee67fd08bea9ed Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:07:28 -0500 Subject: [PATCH 270/428] ASoC: Intel: sof_sdw: fix typo in components string The component string attributes are separated by spaces, not commas. Fixes: b1ca2f63e20b4 ("ASoC: Intel: sof_sdw: add amp number in components string for ucm") Reported-by: Jaroslav Kysela Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200515210731.10942-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index bbbc802624f8..47820316df57 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -945,7 +945,7 @@ static int mc_probe(struct platform_device *pdev) amp_num += codec_info_list[i].amp_num; card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "cfg-spk:%d, cfg-amp:%d", + "cfg-spk:%d cfg-amp:%d", (sof_sdw_quirk & SOF_SDW_FOUR_SPK) ? 4 : 2, amp_num); if (!card->components) From 1f64a08bd5a9a218deb37c03c1e98e9567379698 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:07:29 -0500 Subject: [PATCH 271/428] ASoC: Intel: sof_sdw_rt711: remap buttons Use same mapping as in all other machine drivers: BTN_0 : KEY_PLAYPAUSE BTN_1 : KEY_VOICECOMMAND BTN_2 : KEY_VOLUMEUP BTN_3 : KEY_VOLUMEDOWN Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20200515210731.10942-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_rt711.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 1ded5d9895cf..d4d75c8dc6b7 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -119,10 +119,10 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) jack = &ctx->sdw_headset; - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_PLAYPAUSE); - 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_0, KEY_PLAYPAUSE); + 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); From e6d5cb3ba13e6e54d3ac8cdf891d38042b7c36c5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:07:30 -0500 Subject: [PATCH 272/428] ASoC: Intel: sof_sdw_rt700: remap buttons Use same mapping as in all other machine drivers: BTN_0 : KEY_PLAYPAUSE BTN_1 : KEY_VOICECOMMAND BTN_2 : KEY_VOLUMEUP BTN_3 : KEY_VOLUMEDOWN Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20200515210731.10942-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_rt700.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index 5515f397a3dd..5f50491ba5ee 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -95,10 +95,10 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd) jack = &ctx->sdw_headset; - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_PLAYPAUSE); - 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_0, KEY_PLAYPAUSE); + 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 47f98c55a50c26359b25533810da3724f08113af Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 May 2020 16:07:31 -0500 Subject: [PATCH 273/428] ASoC: Intel: cht_bsw_nau8824: remap BTN_0 as KEY_PLAYPAUSE Use same mapping as in all other machine drivers: BTN_0 : KEY_PLAYPAUSE BTN_1 : KEY_VOICECOMMAND BTN_2 : KEY_VOLUMEUP BTN_3 : KEY_VOLUMEDOWN Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20200515210731.10942-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_nau8824.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index f456150f89c2..67b46de2f088 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -108,7 +108,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) } /* NAU88L24 supports 4 butons headset detection - * KEY_MEDIA + * KEY_PLAYPAUSE * KEY_VOICECOMMAND * KEY_VOLUMEUP * KEY_VOLUMEDOWN @@ -122,7 +122,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) "Headset Jack creation failed %d\n", ret); return ret; } - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 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); From 95579eaf98f17b97dc174bb31d71902b5895bd85 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 11 May 2020 15:25:40 +0200 Subject: [PATCH 274/428] ASoC: da7213: Add da7212 DT compatible This adds a compatible for da7212. It's handled exactly the same way as DA7213 and follows the ACPI bindings. Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20200511132544.82364-2-sebastian.reichel@collabora.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/da7213.txt | 4 ++-- sound/soc/codecs/da7213.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/da7213.txt b/Documentation/devicetree/bindings/sound/da7213.txt index 58902802d56c..69ed23b25e25 100644 --- a/Documentation/devicetree/bindings/sound/da7213.txt +++ b/Documentation/devicetree/bindings/sound/da7213.txt @@ -1,9 +1,9 @@ -Dialog Semiconductor DA7213 Audio Codec bindings +Dialog Semiconductor DA7212/DA7213 Audio Codec bindings ====== Required properties: -- compatible : Should be "dlg,da7213" +- compatible : Should be "dlg,da7212" or "dlg,da7213" - reg: Specifies the I2C slave address Optional properties: diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 925a03996db4..aff306bb58df 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1571,6 +1571,7 @@ static int da7213_set_bias_level(struct snd_soc_component *component, #if defined(CONFIG_OF) /* DT */ static const struct of_device_id da7213_of_match[] = { + { .compatible = "dlg,da7212", }, { .compatible = "dlg,da7213", }, { } }; From b2a378816d0f6780a5500f4322e5b2542d41532d Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 11 May 2020 15:25:41 +0200 Subject: [PATCH 275/428] ASoC: da7213: Add regulator support This adds support for most regulators of da7212 for improved power management. The only thing skipped was the speaker supply, which has some undocumented dependencies. It's supposed to be either always-enabled or always-disabled. Signed-off-by: Sebastian Reichel Reviewed-by: Adam Thomson Link: https://lore.kernel.org/r/20200511132544.82364-3-sebastian.reichel@collabora.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/da7213.txt | 4 + sound/soc/codecs/da7213.c | 79 ++++++++++++++++++- sound/soc/codecs/da7213.h | 9 +++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/da7213.txt b/Documentation/devicetree/bindings/sound/da7213.txt index 69ed23b25e25..94584c96c4ae 100644 --- a/Documentation/devicetree/bindings/sound/da7213.txt +++ b/Documentation/devicetree/bindings/sound/da7213.txt @@ -21,6 +21,10 @@ Optional properties: - dlg,dmic-clkrate : DMIC clock frequency (Hz). [<1500000>, <3000000>] + - VDDA-supply : Regulator phandle for Analogue power supply + - VDDMIC-supply : Regulator phandle for Mic Bias + - VDDIO-supply : Regulator phandle for I/O power supply + ====== Example: diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index aff306bb58df..0359249118d0 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -806,6 +807,11 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, */ static const struct snd_soc_dapm_widget da7213_dapm_widgets[] = { + /* + * Power Supply + */ + SND_SOC_DAPM_REGULATOR_SUPPLY("VDDMIC", 0, 0), + /* * Input & Output */ @@ -932,6 +938,9 @@ static const struct snd_soc_dapm_route da7213_audio_map[] = { /* Dest Connecting Widget source */ /* Input path */ + {"Mic Bias 1", NULL, "VDDMIC"}, + {"Mic Bias 2", NULL, "VDDMIC"}, + {"MIC1", NULL, "Mic Bias 1"}, {"MIC2", NULL, "Mic Bias 2"}, @@ -1691,6 +1700,8 @@ static int da7213_probe(struct snd_soc_component *component) { struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); + pm_runtime_get_sync(component->dev); + /* Default to using ALC auto offset calibration mode. */ snd_soc_component_update_bits(component, DA7213_ALC_CTRL1, DA7213_ALC_CALIB_MODE_MAN, 0); @@ -1811,6 +1822,8 @@ static int da7213_probe(struct snd_soc_component *component) DA7213_DMIC_CLK_RATE_MASK, dmic_cfg); } + pm_runtime_put_sync(component->dev); + /* Check if MCLK provided */ da7213->mclk = devm_clk_get(component->dev, "mclk"); if (IS_ERR(da7213->mclk)) { @@ -1848,11 +1861,22 @@ static const struct regmap_config da7213_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static void da7213_power_off(void *data) +{ + struct da7213_priv *da7213 = data; + regulator_bulk_disable(DA7213_NUM_SUPPLIES, da7213->supplies); +} + +static const char *da7213_supply_names[DA7213_NUM_SUPPLIES] = { + [DA7213_SUPPLY_VDDA] = "VDDA", + [DA7213_SUPPLY_VDDIO] = "VDDIO", +}; + static int da7213_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct da7213_priv *da7213; - int ret; + int i, ret; da7213 = devm_kzalloc(&i2c->dev, sizeof(*da7213), GFP_KERNEL); if (!da7213) @@ -1860,6 +1884,25 @@ static int da7213_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, da7213); + /* Get required supplies */ + for (i = 0; i < DA7213_NUM_SUPPLIES; ++i) + da7213->supplies[i].supply = da7213_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, DA7213_NUM_SUPPLIES, + da7213->supplies); + if (ret) { + dev_err(&i2c->dev, "Failed to get supplies: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(DA7213_NUM_SUPPLIES, da7213->supplies); + if (ret < 0) + return ret; + + ret = devm_add_action_or_reset(&i2c->dev, da7213_power_off, da7213); + if (ret < 0) + return ret; + da7213->regmap = devm_regmap_init_i2c(i2c, &da7213_regmap_config); if (IS_ERR(da7213->regmap)) { ret = PTR_ERR(da7213->regmap); @@ -1867,6 +1910,11 @@ static int da7213_i2c_probe(struct i2c_client *i2c, return ret; } + pm_runtime_set_autosuspend_delay(&i2c->dev, 100); + pm_runtime_use_autosuspend(&i2c->dev); + pm_runtime_set_active(&i2c->dev); + pm_runtime_enable(&i2c->dev); + ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_da7213, &da7213_dai, 1); if (ret < 0) { @@ -1876,6 +1924,34 @@ static int da7213_i2c_probe(struct i2c_client *i2c, return ret; } +static int __maybe_unused da7213_runtime_suspend(struct device *dev) +{ + struct da7213_priv *da7213 = dev_get_drvdata(dev); + + regcache_cache_only(da7213->regmap, true); + regcache_mark_dirty(da7213->regmap); + regulator_bulk_disable(DA7213_NUM_SUPPLIES, da7213->supplies); + + return 0; +} + +static int __maybe_unused da7213_runtime_resume(struct device *dev) +{ + struct da7213_priv *da7213 = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(DA7213_NUM_SUPPLIES, da7213->supplies); + if (ret < 0) + return ret; + regcache_cache_only(da7213->regmap, false); + regcache_sync(da7213->regmap); + return 0; +} + +static const struct dev_pm_ops da7213_pm = { + SET_RUNTIME_PM_OPS(da7213_runtime_suspend, da7213_runtime_resume, NULL) +}; + static const struct i2c_device_id da7213_i2c_id[] = { { "da7213", 0 }, { } @@ -1888,6 +1964,7 @@ static struct i2c_driver da7213_i2c_driver = { .name = "da7213", .of_match_table = of_match_ptr(da7213_of_match), .acpi_match_table = ACPI_PTR(da7213_acpi_match), + .pm = &da7213_pm, }, .probe = da7213_i2c_probe, .id_table = da7213_i2c_id, diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h index 3250a3821fcc..3890829dfb6e 100644 --- a/sound/soc/codecs/da7213.h +++ b/sound/soc/codecs/da7213.h @@ -12,6 +12,7 @@ #include #include +#include #include /* @@ -521,9 +522,17 @@ enum da7213_sys_clk { DA7213_SYSCLK_PLL_32KHZ }; +/* Regulators */ +enum da7213_supplies { + DA7213_SUPPLY_VDDA = 0, + DA7213_SUPPLY_VDDIO, + DA7213_NUM_SUPPLIES, +}; + /* Codec private data */ struct da7213_priv { struct regmap *regmap; + struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES]; struct clk *mclk; unsigned int mclk_rate; int clk_src; From 9c5c258438b23cacc4971b94d808ba8af9c5931c Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 11 May 2020 15:25:42 +0200 Subject: [PATCH 276/428] ASoC: da7213: move set_sysclk to codec level Move set_sysclk function to component level, so that it can be used at both component and DAI level. Signed-off-by: Sebastian Reichel Reviewed-by: Adam Thomson Link: https://lore.kernel.org/r/20200511132544.82364-4-sebastian.reichel@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7213.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 0359249118d0..9686948b16ea 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1343,10 +1343,10 @@ static int da7213_mute(struct snd_soc_dai *dai, int mute) #define DA7213_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) -static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) +static int da7213_set_component_sysclk(struct snd_soc_component *component, + int clk_id, int source, + unsigned int freq, int dir) { - struct snd_soc_component *component = codec_dai->component; struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); int ret = 0; @@ -1354,7 +1354,7 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, return 0; if (((freq < 5000000) && (freq != 32768)) || (freq > 54000000)) { - dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", + dev_err(component->dev, "Unsupported MCLK value %d\n", freq); return -EINVAL; } @@ -1370,7 +1370,7 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, DA7213_PLL_MCLK_SQR_EN); break; default: - dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); + dev_err(component->dev, "Unknown clock source %d\n", clk_id); return -EINVAL; } @@ -1380,7 +1380,7 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, freq = clk_round_rate(da7213->mclk, freq); ret = clk_set_rate(da7213->mclk, freq); if (ret) { - dev_err(codec_dai->dev, "Failed to set clock rate %d\n", + dev_err(component->dev, "Failed to set clock rate %d\n", freq); return ret; } @@ -1507,7 +1507,6 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, static const struct snd_soc_dai_ops da7213_dai_ops = { .hw_params = da7213_hw_params, .set_fmt = da7213_set_dai_fmt, - .set_sysclk = da7213_set_dai_sysclk, .set_pll = da7213_set_dai_pll, .digital_mute = da7213_mute, }; @@ -1845,6 +1844,7 @@ static const struct snd_soc_component_driver soc_component_dev_da7213 = { .num_dapm_widgets = ARRAY_SIZE(da7213_dapm_widgets), .dapm_routes = da7213_audio_map, .num_dapm_routes = ARRAY_SIZE(da7213_audio_map), + .set_sysclk = da7213_set_component_sysclk, .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, From f7a8ae295ca8e96e287f497506b49b1f4b47deb4 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 11 May 2020 15:25:43 +0200 Subject: [PATCH 277/428] ASoC: da7213: move set_pll to codec level Move set_pll function to component level, so that it can be used at both component and DAI level. Signed-off-by: Sebastian Reichel Reviewed-by: Adam Thomson Link: https://lore.kernel.org/r/20200511132544.82364-5-sebastian.reichel@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7213.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 9686948b16ea..3e6ad996741b 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1392,10 +1392,10 @@ static int da7213_set_component_sysclk(struct snd_soc_component *component, } /* Supported PLL input frequencies are 32KHz, 5MHz - 54MHz. */ -static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int fref, unsigned int fout) +static int da7213_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, + unsigned int fref, unsigned int fout) { - struct snd_soc_component *component = codec_dai->component; struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); u8 pll_ctrl, indiv_bits, indiv; @@ -1507,7 +1507,6 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, static const struct snd_soc_dai_ops da7213_dai_ops = { .hw_params = da7213_hw_params, .set_fmt = da7213_set_dai_fmt, - .set_pll = da7213_set_dai_pll, .digital_mute = da7213_mute, }; @@ -1845,6 +1844,7 @@ static const struct snd_soc_component_driver soc_component_dev_da7213 = { .dapm_routes = da7213_audio_map, .num_dapm_routes = ARRAY_SIZE(da7213_audio_map), .set_sysclk = da7213_set_component_sysclk, + .set_pll = da7213_set_component_pll, .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, From d9051d86ad30ca1ef1fc99e29854daeeb3944f8f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:21 +0900 Subject: [PATCH 278/428] ASoC: soc-pcm: replace snd_soc_runtime_activate()/deactivate() to macro snd_soc_runtime_activate()/deactivate() are implemented by global function which are just calling snd_soc_runtime_action(). We can replace it to macro, and this patch do it. This patch is prepare for xxx_active cleanup. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87blmq6n4y.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 15 ++++++++++++-- sound/soc/soc-pcm.c | 49 ++++++++++++++------------------------------- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 69a82487fa9b..a7fa64260108 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -468,8 +468,19 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); -void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); -void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); + +void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, + int stream, int action); +static inline void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, + int stream) +{ + snd_soc_runtime_action(rtd, stream, 1); +} +static inline void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, + int stream) +{ + snd_soc_runtime_action(rtd, stream, -1); +} int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hardware *hw, int stream); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 440c7e87829a..e7175afd9a73 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -256,8 +256,20 @@ static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, return 0; } -static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, - int stream, int action) +/** + * snd_soc_runtime_action() - Increment/Decrement active count for + * PCM runtime components + * @rtd: ASoC PCM runtime that is activated + * @stream: Direction of the PCM stream + * + * Increments/Decrements the active count for all the DAIs and components + * attached to a PCM runtime. + * Should typically be called when a stream is opened. + * + * Must be called with the rtd->card->pcm_mutex being held + */ +void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, + int stream, int action) { struct snd_soc_dai *dai; int i; @@ -270,38 +282,7 @@ static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, dai->component->active += action; } } - -/** - * snd_soc_runtime_activate() - Increment active count for PCM runtime components - * @rtd: ASoC PCM runtime that is activated - * @stream: Direction of the PCM stream - * - * Increments the active count for all the DAIs and components attached to a PCM - * runtime. Should typically be called when a stream is opened. - * - * Must be called with the rtd->card->pcm_mutex being held - */ -void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) -{ - snd_soc_runtime_action(rtd, stream, 1); -} -EXPORT_SYMBOL_GPL(snd_soc_runtime_activate); - -/** - * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components - * @rtd: ASoC PCM runtime that is deactivated - * @stream: Direction of the PCM stream - * - * Decrements the active count for all the DAIs and components attached to a PCM - * runtime. Should typically be called when a stream is closed. - * - * Must be called with the rtd->card->pcm_mutex being held - */ -void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) -{ - snd_soc_runtime_action(rtd, stream, -1); -} -EXPORT_SYMBOL_GPL(snd_soc_runtime_deactivate); +EXPORT_SYMBOL_GPL(snd_soc_runtime_action); /** * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay From dc82910682ef06d5e5a81b4b359945b6f669ee3b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:27 +0900 Subject: [PATCH 279/428] ASoC: soc-dai: add snd_soc_dai_action() snd_soc_runtime_action() updates DAI's xxx_active. We should update these in the same time, and it can be implemented at soc-dai.c. This patch adds snd_soc_dai_action() for it. This is prepare for xxx_active cleanup. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87a72a6n4s.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 12 ++++++++++++ sound/soc/soc-dai.c | 9 +++++++++ sound/soc/soc-pcm.c | 7 ++----- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 2a0a5af1c1ae..800d7aa8523e 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -161,6 +161,18 @@ void snd_soc_dai_resume(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); +void snd_soc_dai_action(struct snd_soc_dai *dai, + int stream, int action); +static inline void snd_soc_dai_activate(struct snd_soc_dai *dai, + int stream) +{ + snd_soc_dai_action(dai, stream, 1); +} +static inline void snd_soc_dai_deactivate(struct snd_soc_dai *dai, + int stream) +{ + snd_soc_dai_action(dai, stream, -1); +} int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 8e5fe012aa1d..3208f244c1b8 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -388,6 +388,15 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) return stream->channels_min; } +void snd_soc_dai_action(struct snd_soc_dai *dai, + int stream, int action) +{ + dai->stream_active[stream] += action; + dai->active += action; + dai->component->active += action; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_action); + int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) { struct snd_soc_dai *dai; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e7175afd9a73..8d414f0ae2f9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -276,11 +276,8 @@ void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, lockdep_assert_held(&rtd->card->pcm_mutex); - for_each_rtd_dais(rtd, i, dai) { - dai->stream_active[stream] += action; - dai->active += action; - dai->component->active += action; - } + for_each_rtd_dais(rtd, i, dai) + snd_soc_dai_action(dai, stream, action); } EXPORT_SYMBOL_GPL(snd_soc_runtime_action); From 45eb8666e52d2d1733fda7353e48906d34a71e5d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:33 +0900 Subject: [PATCH 280/428] ASoC: soc-dapm: use snd_soc_dai_activate()/deactivate() soc-dapm.c :: snd_soc_dai_link_event_pre_pmu() / snd_soc_dai_link_event() are directly updating dai->active without caring about stream_active / component->active. It is breaking xxx_active count balance. This patch uses snd_soc_dai_action() for it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/878shu6n4n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 80658d13a855..a4de3e4bc2ef 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3835,7 +3835,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, "ASoC: startup() failed: %d\n", ret); goto out; } - source->active++; + snd_soc_dai_activate(source, substream->stream); } substream->stream = SNDRV_PCM_STREAM_PLAYBACK; @@ -3848,7 +3848,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, "ASoC: startup() failed: %d\n", ret); goto out; } - sink->active++; + snd_soc_dai_activate(sink, substream->stream); } substream->hw_opened = 1; @@ -3978,14 +3978,14 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, substream->stream = SNDRV_PCM_STREAM_CAPTURE; snd_soc_dapm_widget_for_each_source_path(w, path) { source = path->source->priv; - source->active--; + snd_soc_dai_deactivate(source, substream->stream); snd_soc_dai_shutdown(source, substream); } substream->stream = SNDRV_PCM_STREAM_PLAYBACK; snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; - sink->active--; + snd_soc_dai_deactivate(sink, substream->stream); snd_soc_dai_shutdown(sink, substream); } break; From efffd9b344adbf813e3ae6f6136df80000bf2833 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:37 +0900 Subject: [PATCH 281/428] ASoC: soc-dai: add snd_soc_dai_active() Current snd_soc_dai_action() is updating dai->stream_active for Playback/Capture (A), dai->active for DAI (B) void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action) { (A) dai->stream_active[stream] += action; (B) dai->active += action; dai->component->active += action; } But, these are very verbose, because we can calculate DAI active from stream_active. This patch adds snd_soc_dai_active() which calculate DAI active from DAI stream_active. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/877dxe6n4i.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + sound/soc/soc-dai.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 800d7aa8523e..2c74c41f9447 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -173,6 +173,7 @@ static inline void snd_soc_dai_deactivate(struct snd_soc_dai *dai, { snd_soc_dai_action(dai, stream, -1); } +int snd_soc_dai_active(struct snd_soc_dai *dai); int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 3208f244c1b8..de2981fa5372 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -397,6 +397,18 @@ void snd_soc_dai_action(struct snd_soc_dai *dai, } EXPORT_SYMBOL_GPL(snd_soc_dai_action); +int snd_soc_dai_active(struct snd_soc_dai *dai) +{ + int stream, active; + + active = 0; + for_each_pcm_streams(stream) + active += dai->stream_active[stream]; + + return active; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_active); + int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) { struct snd_soc_dai *dai; From 488b2ca599f96d46d4a4d730845a247328cb6a28 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:42 +0900 Subject: [PATCH 282/428] ASoC: soc-component: add snd_soc_component_active() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/875zcy6n4d.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 6 ++++++ sound/soc/soc-dai.c | 1 + 2 files changed, 7 insertions(+) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 864983b09846..f39e1084850e 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -395,6 +395,12 @@ static inline bool snd_soc_component_is_active( return component->active != 0; } +static inline unsigned int +snd_soc_component_active(struct snd_soc_component *component) +{ + return component->active; +} + /* component pin */ int snd_soc_component_enable_pin(struct snd_soc_component *component, const char *pin); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index de2981fa5372..bb771302fd6f 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -393,6 +393,7 @@ void snd_soc_dai_action(struct snd_soc_dai *dai, { dai->stream_active[stream] += action; dai->active += action; + /* see snd_soc_component_active() */ dai->component->active += action; } EXPORT_SYMBOL_GPL(snd_soc_dai_action); From 5552f8d72893cea29a0074a3ea0a1a5766858fcd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:47 +0900 Subject: [PATCH 283/428] ASoC: soc-dai: add snd_soc_dai_stream_active() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/874ksi6n48.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 6 ++++++ sound/soc/soc-dai.c | 1 + 2 files changed, 7 insertions(+) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 2c74c41f9447..8826a129ccf9 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -481,4 +481,10 @@ static inline void *snd_soc_dai_get_sdw_stream(struct snd_soc_dai *dai, return ERR_PTR(-ENOTSUPP); } +static inline unsigned int +snd_soc_dai_stream_active(struct snd_soc_dai *dai, int stream) +{ + return dai->stream_active[stream]; +} + #endif diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index bb771302fd6f..8172ff42d796 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -391,6 +391,7 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action) { + /* see snd_soc_dai_stream_active() */ dai->stream_active[stream] += action; dai->active += action; /* see snd_soc_component_active() */ From b3dea624b52e8b18cd49f804ce70fe50374aa5db Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:51 +0900 Subject: [PATCH 284/428] ASoC: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/8736826n44.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 4 ++-- sound/soc/soc-core.c | 11 ++++++----- sound/soc/soc-pcm.c | 20 ++++++++++---------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index def3ae78b4a7..62ece729e425 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -231,10 +231,10 @@ static int soc_compr_free(struct snd_compr_stream *cstream) snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); - if (!cpu_dai->active) + if (!snd_soc_dai_active(cpu_dai)) cpu_dai->rate = 0; - if (!codec_dai->active) + if (!snd_soc_dai_active(codec_dai)) codec_dai->rate = 0; if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 95d8189e45ab..e697258d2ffc 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -372,7 +372,8 @@ void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", codec_dai->driver->playback.stream_name, - codec_dai->stream_active[playback] ? "active" : "inactive", + snd_soc_dai_stream_active(codec_dai, playback) ? + "active" : "inactive", rtd->pop_wait ? "yes" : "no"); /* are we waiting on this codec DAI stream */ @@ -546,7 +547,7 @@ int snd_soc_suspend(struct device *dev) continue; for_each_rtd_codec_dais(rtd, i, dai) { - if (dai->stream_active[playback]) + if (snd_soc_dai_stream_active(dai, playback)) snd_soc_dai_digital_mute(dai, 1, playback); } } @@ -688,7 +689,7 @@ static void soc_resume_deferred(struct work_struct *work) continue; for_each_rtd_codec_dais(rtd, i, dai) { - if (dai->stream_active[playback]) + if (snd_soc_dai_stream_active(dai, playback)) snd_soc_dai_digital_mute(dai, 0, playback); } } @@ -718,7 +719,7 @@ int snd_soc_resume(struct device *dev) /* activate pins from sleep state */ for_each_card_components(card, component) - if (component->active) + if (snd_soc_component_active(component)) pinctrl_pm_select_default_state(component->dev); dev_dbg(dev, "ASoC: Scheduling resume work\n"); @@ -1943,7 +1944,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) /* deactivate pins to sleep state */ for_each_card_components(card, component) - if (!component->active) + if (!snd_soc_component_active(component)) pinctrl_pm_select_sleep_state(component->dev); probe_end: diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8d414f0ae2f9..b7899da4217e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -750,7 +750,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) } for_each_rtd_components(rtd, i, component) - if (!component->active) + if (!snd_soc_component_active(component)) pinctrl_pm_select_sleep_state(component->dev); return 0; @@ -844,7 +844,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) /* Symmetry only applies if we've already got an active stream. */ for_each_rtd_dais(rtd, i, dai) { - if (dai->active) { + if (snd_soc_dai_active(dai)) { ret = soc_pcm_apply_symmetry(substream, dai); if (ret != 0) goto config_err; @@ -882,7 +882,7 @@ component_err: } for_each_rtd_components(rtd, i, component) - if (!component->active) + if (!snd_soc_component_active(component)) pinctrl_pm_select_sleep_state(component->dev); return ret; @@ -1136,9 +1136,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) /* clear the corresponding DAIs parameters when going to be inactive */ for_each_rtd_dais(rtd, i, dai) { - int active = dai->stream_active[substream->stream]; + int active = snd_soc_dai_stream_active(dai, substream->stream); - if (dai->active == 1) { + if (snd_soc_dai_active(dai) == 1) { dai->rate = 0; dai->channels = 0; dai->sample_bits = 0; @@ -1907,7 +1907,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, for_each_rtd_cpu_dais (fe, i, fe_cpu_dai) { /* Symmetry only applies if we've got an active stream. */ - if (fe_cpu_dai->active) { + if (snd_soc_dai_active(fe_cpu_dai)) { err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai); if (err < 0) return err; @@ -1936,7 +1936,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, /* Symmetry only applies if we've got an active stream. */ for_each_rtd_dais(rtd, i, dai) { - if (dai->active) { + if (snd_soc_dai_active(dai)) { err = soc_pcm_apply_symmetry(fe_substream, dai); if (err < 0) return err; @@ -2709,7 +2709,7 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) return 0; /* only check active links */ - if (!asoc_rtd_to_cpu(fe, 0)->active) + if (!snd_soc_dai_active(asoc_rtd_to_cpu(fe, 0))) return 0; /* DAPM sync will call this to update DSP paths */ @@ -2724,8 +2724,8 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) continue; /* skip if FE isn't currently playing/capturing */ - if (!asoc_rtd_to_cpu(fe, 0)->stream_active[stream] || - !asoc_rtd_to_codec(fe, 0)->stream_active[stream]) + if (!snd_soc_dai_stream_active(asoc_rtd_to_cpu(fe, 0), stream) || + !snd_soc_dai_stream_active(asoc_rtd_to_codec(fe, 0), stream)) continue; paths = dpcm_path_get(fe, stream, &list); From e1c7e1faa404df564e64785c0b5cb7f1ee2d785d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:56 +0900 Subject: [PATCH 285/428] ASoC: atomel: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/871rnm6n3z.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_ssc_dai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 1073f468f21f..0f18dfb85bfe 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -765,7 +765,7 @@ static int atmel_ssc_suspend(struct snd_soc_component *component) struct atmel_ssc_info *ssc_p; struct platform_device *pdev = to_platform_device(component->dev); - if (!component->active) + if (!snd_soc_component_active(component)) return 0; ssc_p = &ssc_info[pdev->id]; @@ -793,7 +793,7 @@ static int atmel_ssc_resume(struct snd_soc_component *component) struct platform_device *pdev = to_platform_device(component->dev); u32 cr; - if (!component->active) + if (!snd_soc_component_active(component)) return 0; ssc_p = &ssc_info[pdev->id]; From 8ca4602d38c5140ae2cbeec9f1dd7803b0c4d61d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:01 +0900 Subject: [PATCH 286/428] ASoC: bcm: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87zhaa58je.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 6 +++--- sound/soc/bcm/cygnus-ssp.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index e6a12e271b07..d80b570e950e 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -653,7 +653,7 @@ static void bcm2835_i2s_stop(struct bcm2835_i2s_dev *dev, BCM2835_I2S_CS_A_REG, mask, 0); /* Stop also the clock when not SND_SOC_DAIFMT_CONT */ - if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) + if (!snd_soc_dai_active(dai) && !(dev->fmt & SND_SOC_DAIFMT_CONT)) bcm2835_i2s_stop_clock(dev); } @@ -695,7 +695,7 @@ static int bcm2835_i2s_startup(struct snd_pcm_substream *substream, { struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); - if (dai->active) + if (snd_soc_dai_active(dai)) return 0; /* Should this still be running stop it */ @@ -723,7 +723,7 @@ static void bcm2835_i2s_shutdown(struct snd_pcm_substream *substream, bcm2835_i2s_stop(dev, substream, dai); /* If both streams are stopped, disable module and clock */ - if (dai->active) + if (snd_soc_dai_active(dai)) return; /* Disable the module */ diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index 257f5048061e..6e634b448293 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c @@ -1056,7 +1056,7 @@ static int __cygnus_ssp_suspend(struct snd_soc_dai *cpu_dai) { struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai); - if (!cpu_dai->active) + if (!snd_soc_dai_active(cpu_dai)) return 0; if (!aio->is_slave) { @@ -1097,7 +1097,7 @@ static int __cygnus_ssp_resume(struct snd_soc_dai *cpu_dai) struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai); int error; - if (!cpu_dai->active) + if (!snd_soc_dai_active(cpu_dai)) return 0; if (!aio->is_slave) { From 90a61a549df10082463c1ec37bc378799febe8a9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:05 +0900 Subject: [PATCH 287/428] ASoC: cirrus: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87y2pu58ja.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 723f4cf19467..371708b17c09 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -368,7 +368,7 @@ static int ep93xx_i2s_suspend(struct snd_soc_component *component) { struct ep93xx_i2s_info *info = snd_soc_component_get_drvdata(component); - if (!component->active) + if (!snd_soc_component_active(component)) return 0; ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); @@ -381,7 +381,7 @@ static int ep93xx_i2s_resume(struct snd_soc_component *component) { struct ep93xx_i2s_info *info = snd_soc_component_get_drvdata(component); - if (!component->active) + if (!snd_soc_component_active(component)) return 0; ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); From 5e518eddd11e8f71aaffc954dc7ee9572fc59808 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:11 +0900 Subject: [PATCH 288/428] ASoC: codecs: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87wo5e58j4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/adav80x.c | 4 ++-- sound/soc/codecs/arizona.c | 2 +- sound/soc/codecs/cs4271.c | 4 ++-- sound/soc/codecs/madera.c | 2 +- sound/soc/codecs/max98090.c | 6 +++--- sound/soc/codecs/tlv320aic23.c | 2 +- sound/soc/codecs/tlv320dac33.c | 2 +- sound/soc/codecs/uda1380.c | 2 +- sound/soc/codecs/wl1273.c | 2 +- sound/soc/codecs/wm8711.c | 2 +- sound/soc/codecs/wm8753.c | 4 ++-- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 7cea398ec392..c4b9722c3d8f 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -725,7 +725,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct adav80x *adav80x = snd_soc_component_get_drvdata(component); - if (!snd_soc_component_is_active(component) || !adav80x->rate) + if (!snd_soc_component_active(component) || !adav80x->rate) return 0; return snd_pcm_hw_constraint_single(substream->runtime, @@ -738,7 +738,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct adav80x *adav80x = snd_soc_component_get_drvdata(component); - if (!snd_soc_component_is_active(component)) + if (!snd_soc_component_active(component)) adav80x->rate = 0; } diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 70341b30f567..9716c9624a89 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1926,7 +1926,7 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, if (clk_id == dai_priv->clk) return 0; - if (dai->active) { + if (snd_soc_dai_active(dai)) { dev_err(component->dev, "Can't change clock on active DAI %d\n", dai->id); return -EBUSY; diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 62f412d6f9f2..d43762ae8f3d 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -356,9 +356,9 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - !dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]) || + !snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)) || (substream->stream == SNDRV_PCM_STREAM_CAPTURE && - !dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK])) { + !snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK))) { ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN, CS4271_MODE2_PDN); diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index a448d2a2918a..ec380b0b2d4e 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -3279,7 +3279,7 @@ static int madera_dai_set_sysclk(struct snd_soc_dai *dai, if (is_sync == madera_is_syncclk(dai_priv->clk)) return 0; - if (dai->active) { + if (snd_soc_dai_active(dai)) { dev_err(component->dev, "Can't change clock on active DAI %d\n", dai->id); return -EBUSY; diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 032adc14562d..e2cc1ad8cb0a 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2039,7 +2039,7 @@ static int max98090_dai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!max98090->master && dai->active == 1) + if (!max98090->master && snd_soc_dai_active(dai) == 1) queue_delayed_work(system_power_efficient_wq, &max98090->pll_det_enable_work, msecs_to_jiffies(10)); @@ -2047,7 +2047,7 @@ static int max98090_dai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (!max98090->master && dai->active == 1) + if (!max98090->master && snd_soc_dai_active(dai) == 1) schedule_work(&max98090->pll_det_disable_work); break; default: @@ -2109,7 +2109,7 @@ static void max98090_pll_work(struct max98090_priv *max98090) unsigned int pll; int i; - if (!snd_soc_component_is_active(component)) + if (!snd_soc_component_active(component)) return; dev_info_ratelimited(component->dev, "PLL unlocked\n"); diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index f8e2f4b74db3..9868fb22323c 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -394,7 +394,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, struct aic23 *aic23 = snd_soc_component_get_drvdata(component); /* deactivate */ - if (!snd_soc_component_is_active(component)) { + if (!snd_soc_component_active(component)) { udelay(50); snd_soc_component_write(component, TLV320AIC23_ACTIVE, 0x0); } diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 808654b10deb..d905e03aaec7 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -449,7 +449,7 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol, if (dac33->fifo_mode == ucontrol->value.enumerated.item[0]) return 0; /* Do not allow changes while stream is running*/ - if (snd_soc_component_is_active(component)) + if (snd_soc_component_active(component)) return -EPERM; if (ucontrol->value.enumerated.item[0] >= DAC33_FIFO_LAST_MODE) diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 26b2ee428aee..89f2bfeeb70e 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -110,7 +110,7 @@ static int uda1380_write(struct snd_soc_component *component, unsigned int reg, /* the interpolator & decimator regs must only be written when the * codec DAI is active. */ - if (!snd_soc_component_is_active(component) && (reg >= UDA1380_MVOL)) + if (!snd_soc_component_active(component) && (reg >= UDA1380_MVOL)) return 0; pr_debug("uda1380: hw write %x val %x\n", reg, value); if (i2c_master_send(uda1380->i2c, data, 3) == 3) { diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index b30bfcd6a125..c56b9329240f 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -183,7 +183,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, return 0; /* Do not allow changes while stream is running */ - if (snd_soc_component_is_active(component)) + if (snd_soc_component_active(component)) return -EPERM; if (ucontrol->value.enumerated.item[0] >= ARRAY_SIZE(wl1273_audio_route)) diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 8036b18fdeb9..5ad905dd78b7 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -198,7 +198,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; /* deactivate */ - if (!snd_soc_component_is_active(component)) { + if (!snd_soc_component_active(component)) { udelay(50); snd_soc_component_write(component, WM8711_ACTIVE, 0x0); } diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 95a12718f3af..8753c55c73fa 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -241,7 +241,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, if (wm8753->dai_func == ucontrol->value.enumerated.item[0]) return 0; - if (snd_soc_component_is_active(component)) + if (snd_soc_component_active(component)) return -EBUSY; ioctl = snd_soc_component_read32(component, WM8753_IOCTL); @@ -1304,7 +1304,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) /* the digital mute covers the HiFi and Voice DAC's on the WM8753. * make sure we check if they are not both active when we mute */ if (mute && wm8753->dai_func == 1) { - if (!snd_soc_component_is_active(component)) + if (!snd_soc_component_active(component)) snd_soc_component_write(component, WM8753_DAC, mute_reg | 0x8); } else { if (mute) From 1d9fb19d8f644bfa17c79660b823b7ad07b0b046 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:17 +0900 Subject: [PATCH 289/428] ASoC: fsl: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87v9ky58iy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 2 +- sound/soc/fsl/fsl_spdif.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index bac65ba7fbad..cbcb70d6f8c8 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -514,7 +514,7 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, { struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); - if (!dai->active) { + if (!snd_soc_dai_active(dai)) { /* Set synchronous mode */ regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR, ESAI_SAICR_SYNC, esai_priv->synchronous ? diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index c711d2d93280..1b2e516f9162 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -466,7 +466,7 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream, int ret; /* Reset module and interrupts only for first initialization */ - if (!cpu_dai->active) { + if (!snd_soc_dai_active(cpu_dai)) { ret = clk_prepare_enable(spdif_priv->coreclk); if (ret) { dev_err(&pdev->dev, "failed to enable core clock\n"); @@ -554,7 +554,7 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream, regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); /* Power down SPDIF module only if tx&rx are both inactive */ - if (!cpu_dai->active) { + if (!snd_soc_dai_active(cpu_dai)) { spdif_intr_status_clear(spdif_priv); regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, SCR_LOW_POWER); From 846d0a17a8042ea753387b7571731d8265b87868 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:22 +0900 Subject: [PATCH 290/428] ASoC: intel: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87tv0i58it.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 2e9222ed9daa..8817eaae6bb7 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -392,7 +392,7 @@ static int sst_enable_ssp(struct snd_pcm_substream *substream, { int ret = 0; - if (!dai->active) { + if (!snd_soc_dai_active(dai)) { ret = sst_handle_vb_timer(dai, true); sst_fill_ssp_defaults(dai); } @@ -405,7 +405,7 @@ static int sst_be_hw_params(struct snd_pcm_substream *substream, { int ret = 0; - if (dai->active == 1) + if (snd_soc_dai_active(dai) == 1) ret = send_ssp_cmd(dai, dai->name, 1); return ret; } @@ -414,7 +414,7 @@ static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt) { int ret = 0; - if (!dai->active) + if (!snd_soc_dai_active(dai)) return 0; ret = sst_fill_ssp_config(dai, fmt); @@ -429,7 +429,7 @@ static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai, int slots, int slot_width) { int ret = 0; - if (!dai->active) + if (!snd_soc_dai_active(dai)) return ret; ret = sst_fill_ssp_slot(dai, tx_mask, rx_mask, slots, slot_width); @@ -442,7 +442,7 @@ static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai, static void sst_disable_ssp(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - if (!dai->active) { + if (!snd_soc_dai_active(dai)) { send_ssp_cmd(dai, dai->name, 0); sst_handle_vb_timer(dai, false); } @@ -743,7 +743,7 @@ static int sst_soc_prepare(struct device *dev) for_each_card_rtds(drv->soc_card, rtd) { struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); - if (dai->active) { + if (snd_soc_dai_active(dai)) { send_ssp_cmd(dai, dai->name, 0); sst_handle_vb_timer(dai, false); } @@ -764,7 +764,7 @@ static void sst_soc_complete(struct device *dev) for_each_card_rtds(drv->soc_card, rtd) { struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); - if (dai->active) { + if (snd_soc_dai_active(dai)) { sst_handle_vb_timer(dai, true); send_ssp_cmd(dai, dai->name, 1); } From 48afb287853effb07253bb2ccad2123f37770a8f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:27 +0900 Subject: [PATCH 291/428] ASoC: jz4740: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87sgg258io.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/jz4740/jz4740-i2s.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 6f6f8dad0356..403630b121f6 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -129,7 +129,7 @@ static int jz4740_i2s_startup(struct snd_pcm_substream *substream, uint32_t conf, ctrl; int ret; - if (dai->active) + if (snd_soc_dai_active(dai)) return 0; ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); @@ -153,7 +153,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); uint32_t conf; - if (dai->active) + if (snd_soc_dai_active(dai)) return; conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); @@ -332,7 +332,7 @@ static int jz4740_i2s_suspend(struct snd_soc_component *component) struct jz4740_i2s *i2s = snd_soc_component_get_drvdata(component); uint32_t conf; - if (component->active) { + if (snd_soc_component_active(component)) { conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); conf &= ~JZ_AIC_CONF_ENABLE; jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); @@ -355,7 +355,7 @@ static int jz4740_i2s_resume(struct snd_soc_component *component) if (ret) return ret; - if (component->active) { + if (snd_soc_component_active(component)) { ret = clk_prepare_enable(i2s->clk_i2s); if (ret) { clk_disable_unprepare(i2s->clk_aic); From 7995981bcfbc150902395af4191a77c9f4b842cd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:31 +0900 Subject: [PATCH 292/428] ASoC: mediatek: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87r1vm58ik.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 1e3f2d786066..1cc044425a9e 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -297,7 +297,7 @@ static int mt8173_afe_i2s_startup(struct snd_pcm_substream *substream, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); - if (dai->active) + if (snd_soc_dai_active(dai)) return 0; regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, @@ -310,7 +310,7 @@ static void mt8173_afe_i2s_shutdown(struct snd_pcm_substream *substream, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); - if (dai->active) + if (snd_soc_dai_active(dai)) return; mt8173_afe_set_i2s_enable(afe, false); @@ -347,7 +347,7 @@ static int mt8173_afe_hdmi_startup(struct snd_pcm_substream *substream, struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8173_afe_private *afe_priv = afe->platform_priv; - if (dai->active) + if (snd_soc_dai_active(dai)) return 0; mt8173_afe_dais_enable_clks(afe, afe_priv->clocks[MT8173_CLK_I2S3_M], @@ -361,7 +361,7 @@ static void mt8173_afe_hdmi_shutdown(struct snd_pcm_substream *substream, struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8173_afe_private *afe_priv = afe->platform_priv; - if (dai->active) + if (snd_soc_dai_active(dai)) return; mt8173_afe_dais_disable_clks(afe, afe_priv->clocks[MT8173_CLK_I2S3_M], From 1f79aab5a44871286d414eb2a289aaeea4236fd1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:36 +0900 Subject: [PATCH 293/428] ASoC: meson: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87pnb658if.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm-interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index d51f3344be7c..6de27238e9df 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -149,7 +149,7 @@ static int axg_tdm_iface_startup(struct snd_pcm_substream *substream, } /* Apply component wide rate symmetry */ - if (dai->component->active) { + if (snd_soc_component_active(dai->component)) { ret = snd_pcm_hw_constraint_single(substream->runtime, SNDRV_PCM_HW_PARAM_RATE, iface->rate); From aaeb5fb59965217789258486080105337483a9e7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:41 +0900 Subject: [PATCH 294/428] ASoC: pxa: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87o8qq58ia.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 8 ++++---- sound/soc/pxa/pxa2xx-i2s.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index e615acaa0199..6a72cc1665b7 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -94,7 +94,7 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, struct snd_dmaengine_dai_dma_data *dma; int ret = 0; - if (!cpu_dai->active) { + if (!snd_soc_dai_active(cpu_dai)) { clk_prepare_enable(ssp->clk); pxa_ssp_disable(ssp); } @@ -119,7 +119,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; - if (!cpu_dai->active) { + if (!snd_soc_dai_active(cpu_dai)) { pxa_ssp_disable(ssp); clk_disable_unprepare(ssp->clk); } @@ -138,7 +138,7 @@ static int pxa_ssp_suspend(struct snd_soc_component *component) struct ssp_priv *priv = snd_soc_component_get_drvdata(component); struct ssp_device *ssp = priv->ssp; - if (!component->active) + if (!snd_soc_component_active(component)) clk_prepare_enable(ssp->clk); priv->cr0 = __raw_readl(ssp->mmio_base + SSCR0); @@ -165,7 +165,7 @@ static int pxa_ssp_resume(struct snd_soc_component *component) __raw_writel(priv->to, ssp->mmio_base + SSTO); __raw_writel(priv->psp, ssp->mmio_base + SSPSP); - if (component->active) + if (snd_soc_component_active(component)) pxa_ssp_enable(ssp); else clk_disable_unprepare(ssp->clk); diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 9a32bf72127a..03102e938ba1 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -101,7 +101,7 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, if (IS_ERR(clk_i2s)) return PTR_ERR(clk_i2s); - if (!cpu_dai->active) + if (!snd_soc_dai_active(cpu_dai)) SACR0 = 0; return 0; From 36ad1a87104e4a54f6acaffbe2d9533f80179e74 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:48 +0900 Subject: [PATCH 295/428] ASoC: ti: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87mu6a58i3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 2 +- sound/soc/ti/omap-dmic.c | 4 ++-- sound/soc/ti/omap-mcbsp.c | 4 ++-- sound/soc/ti/omap-mcpdm.c | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 7a7db743dc5b..b93c1ee302c0 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -1577,7 +1577,7 @@ static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream, if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) return; - if (!cpu_dai->active) { + if (!snd_soc_dai_active(cpu_dai)) { mcasp->channels = 0; mcasp->max_format_width = 0; } diff --git a/sound/soc/ti/omap-dmic.c b/sound/soc/ti/omap-dmic.c index 913579c43e9d..01abf1be5d78 100644 --- a/sound/soc/ti/omap-dmic.c +++ b/sound/soc/ti/omap-dmic.c @@ -95,7 +95,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream, mutex_lock(&dmic->mutex); - if (!dai->active) + if (!snd_soc_dai_active(dai)) dmic->active = 1; else ret = -EBUSY; @@ -114,7 +114,7 @@ static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream, cpu_latency_qos_remove_request(&dmic->pm_qos_req); - if (!dai->active) + if (!snd_soc_dai_active(dai)) dmic->active = 0; mutex_unlock(&dmic->mutex); diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 6c83b9888467..4e67769b795a 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -786,7 +786,7 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); int err = 0; - if (!cpu_dai->active) + if (!snd_soc_dai_active(cpu_dai)) err = omap_mcbsp_request(mcbsp); /* @@ -841,7 +841,7 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, mcbsp->latency[stream1] = 0; - if (!cpu_dai->active) { + if (!snd_soc_dai_active(cpu_dai)) { omap_mcbsp_free(mcbsp); mcbsp->configured = 0; } diff --git a/sound/soc/ti/omap-mcpdm.c b/sound/soc/ti/omap-mcpdm.c index f2dbadea33bb..d482b62f314a 100644 --- a/sound/soc/ti/omap-mcpdm.c +++ b/sound/soc/ti/omap-mcpdm.c @@ -253,7 +253,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, mutex_lock(&mcpdm->mutex); - if (!dai->active) + if (!snd_soc_dai_active(dai)) omap_mcpdm_open_streams(mcpdm); mutex_unlock(&mcpdm->mutex); @@ -271,7 +271,7 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, mutex_lock(&mcpdm->mutex); - if (!dai->active) { + if (!snd_soc_dai_active(dai)) { if (omap_mcpdm_active(mcpdm)) { omap_mcpdm_stop(mcpdm); omap_mcpdm_close_streams(mcpdm); @@ -462,7 +462,7 @@ static int omap_mcpdm_suspend(struct snd_soc_component *component) { struct omap_mcpdm *mcpdm = snd_soc_component_get_drvdata(component); - if (component->active) { + if (snd_soc_component_active(component)) { omap_mcpdm_stop(mcpdm); omap_mcpdm_close_streams(mcpdm); } @@ -484,7 +484,7 @@ static int omap_mcpdm_resume(struct snd_soc_component *component) while (mcpdm->pm_active_count--) pm_runtime_get_sync(mcpdm->dev); - if (component->active) { + if (snd_soc_component_active(component)) { omap_mcpdm_open_streams(mcpdm); omap_mcpdm_start(mcpdm); } From 25d6755213f42ecf0c89f8619747be45e71382ac Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:53 +0900 Subject: [PATCH 296/428] ASoC: uniphier: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87lflu58hy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/uniphier/aio-cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/uniphier/aio-cpu.c b/sound/soc/uniphier/aio-cpu.c index fdaa6522720f..25c40c28eba4 100644 --- a/sound/soc/uniphier/aio-cpu.c +++ b/sound/soc/uniphier/aio-cpu.c @@ -424,7 +424,7 @@ static void uniphier_aio_dai_suspend(struct snd_soc_dai *dai) { struct uniphier_aio *aio = uniphier_priv(dai); - if (!dai->active) + if (!snd_soc_dai_active(dai)) return; aio->chip->num_wup_aios--; @@ -448,7 +448,7 @@ static int uniphier_aio_dai_resume(struct snd_soc_dai *dai) struct uniphier_aio *aio = uniphier_priv(dai); int ret, i; - if (!dai->active) + if (!snd_soc_dai_active(dai)) return 0; if (!aio->chip->active) From 8db4f94fb3088528a8a64e2c39c8bf764a9433b0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:47:57 +0900 Subject: [PATCH 297/428] ASoC: dwc: use snd_soc_xxx_active() We have snd_soc_dai/dai_stream/component_active() macro This patch uses it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87k11e58hu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/dwc/dwc-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 515f88456dbd..fd4160289fac 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -429,7 +429,7 @@ static int dw_i2s_resume(struct snd_soc_component *component) for_each_component_dais(component, dai) { for_each_pcm_streams(stream) - if (dai->stream_active[stream]) + if (snd_soc_dai_stream_active(dai, stream)) dw_i2s_config(dev, stream); } From 0812a08ac8d054efc6cf2895d3b0e82c8731f8e9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:48:02 +0900 Subject: [PATCH 298/428] ASoC: cleanup dai / component active code No one is using dai->active, snd_soc_component_is_active(). Let's remove these. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87imgy58hp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 6 ------ include/sound/soc-dai.h | 2 -- sound/soc/soc-dai.c | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index f39e1084850e..5663891148e3 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -389,12 +389,6 @@ static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c) return dev_get_drvdata(c->dev); } -static inline bool snd_soc_component_is_active( - struct snd_soc_component *component) -{ - return component->active != 0; -} - static inline unsigned int snd_soc_component_active(struct snd_soc_component *component) { diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 8826a129ccf9..212257e84fac 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -364,8 +364,6 @@ struct snd_soc_dai { /* DAI runtime info */ unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1]; /* usage count */ - unsigned int active; - struct snd_soc_dapm_widget *playback_widget; struct snd_soc_dapm_widget *capture_widget; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 8172ff42d796..ce4e1fd1ab79 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -393,7 +393,7 @@ void snd_soc_dai_action(struct snd_soc_dai *dai, { /* see snd_soc_dai_stream_active() */ dai->stream_active[stream] += action; - dai->active += action; + /* see snd_soc_component_active() */ dai->component->active += action; } From 11106cb37ade76719bb3feac9fa6ba68173a38a0 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Mon, 18 May 2020 18:59:51 +0800 Subject: [PATCH 299/428] ASoC: fsl_micfil: Fix indentation to put on one line affected code In the function fsl_micfil_startup(), the two lines of dev_err() can be shortened to one line. Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200518105951.19200-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index e73bd6570a08..d31f027cd9cc 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -217,8 +217,7 @@ static int fsl_micfil_startup(struct snd_pcm_substream *substream, struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai); if (!micfil) { - dev_err(dai->dev, - "micfil dai priv_data not set\n"); + dev_err(dai->dev, "micfil dai priv_data not set\n"); return -EINVAL; } From f0a77d2b0e1ccad7e4086094f67d138e8c3050a2 Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Mon, 18 May 2020 10:09:05 +0530 Subject: [PATCH 300/428] ASoC: amd: raven: Make the driver name consistent across files This fixes the issue of driver not getting auto loaded with MODULE_ALIAS. With this patch: $find /sys/devices -name modalias -print0 | xargs -0 grep -i acp3x /sys/devices/pci0000:00/0000:00:08.1/0000:03:00.5/acp3x_i2s_playcap.2/ modalias:platform:acp3x_i2s_playcap /sys/devices/pci0000:00/0000:00:08.1/0000:03:00.5/acp3x_i2s_playcap.0/ modalias:platform:acp3x_i2s_playcap /sys/devices/pci0000:00/0000:00:08.1/0000:03:00.5/acp3x_rv_i2s_dma.0/ modalias:platform:acp3x_rv_i2s_dma /sys/devices/pci0000:00/0000:00:08.1/0000:03:00.5/acp3x_i2s_playcap.1/ modalias:platform:acp3x_i2s_playcap Signed-off-by: Akshu Agrawal Link: https://lore.kernel.org/r/20200518043913.40646-1-akshu.agrawal@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-i2s.c | 6 +++--- sound/soc/amd/raven/acp3x-pcm-dma.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c index f160d35a6832..a532e01a2622 100644 --- a/sound/soc/amd/raven/acp3x-i2s.c +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -15,7 +15,7 @@ #include "acp3x.h" -#define DRV_NAME "acp3x-i2s" +#define DRV_NAME "acp3x_i2s_playcap" static int acp3x_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) @@ -269,7 +269,7 @@ static struct snd_soc_dai_ops acp3x_i2s_dai_ops = { }; static const struct snd_soc_component_driver acp3x_dai_component = { - .name = "acp3x-i2s", + .name = DRV_NAME, }; static struct snd_soc_dai_driver acp3x_i2s_dai = { @@ -348,4 +348,4 @@ module_platform_driver(acp3x_dai_driver); MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRV_NAME); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index a36c5cb848cd..620b568bc414 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -15,7 +15,7 @@ #include "acp3x.h" -#define DRV_NAME "acp3x-i2s-audio" +#define DRV_NAME "acp3x_rv_i2s_dma" static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = { .info = SNDRV_PCM_INFO_INTERLEAVED | @@ -542,4 +542,4 @@ MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com"); MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRV_NAME); +MODULE_ALIAS("platform:"DRV_NAME); From 15b5c496ff99ce99ab3c5e98e96981d015b3168a Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Mon, 18 May 2020 19:00:40 +0800 Subject: [PATCH 301/428] ASoC: fsl_micfil: Fix unused assignment in fsl_set_clock_params() Delete unused initialized value of 'ret', because it will be assigned by the function fsl_micfil_set_mclk_rate(). Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200518110040.18036-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index d31f027cd9cc..59cf95fa2b2d 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -295,7 +295,7 @@ static int fsl_set_clock_params(struct device *dev, unsigned int rate) { struct fsl_micfil *micfil = dev_get_drvdata(dev); int clk_div; - int ret = 0; + int ret; ret = fsl_micfil_set_mclk_rate(micfil, rate); if (ret < 0) From 8ba4dc3cff8cbe2c571063a5fd7116e8bde563ca Mon Sep 17 00:00:00 2001 From: Pavel Dobias Date: Fri, 15 May 2020 14:07:57 +0200 Subject: [PATCH 302/428] ASoC: max9867: fix volume controls The xmax values for Master Playback Volume and Mic Boost Capture Volume are specified incorrectly (one greater) which results in the wrong dB gain being shown to the user in the case of Master Playback Volume. Signed-off-by: Pavel Dobias Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200515120757.24669-1-dobias@2n.cz Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 8600c5439e1e..2e4aa23b5a60 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -46,13 +46,13 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(max9867_micboost_tlv, static const struct snd_kcontrol_new max9867_snd_controls[] = { SOC_DOUBLE_R_TLV("Master Playback Volume", MAX9867_LEFTVOL, - MAX9867_RIGHTVOL, 0, 41, 1, max9867_master_tlv), + MAX9867_RIGHTVOL, 0, 40, 1, max9867_master_tlv), SOC_DOUBLE_R_TLV("Line Capture Volume", MAX9867_LEFTLINELVL, MAX9867_RIGHTLINELVL, 0, 15, 1, max9867_line_tlv), SOC_DOUBLE_R_TLV("Mic Capture Volume", MAX9867_LEFTMICGAIN, MAX9867_RIGHTMICGAIN, 0, 20, 1, max9867_mic_tlv), SOC_DOUBLE_R_TLV("Mic Boost Capture Volume", MAX9867_LEFTMICGAIN, - MAX9867_RIGHTMICGAIN, 5, 4, 0, max9867_micboost_tlv), + MAX9867_RIGHTMICGAIN, 5, 3, 0, max9867_micboost_tlv), SOC_SINGLE("Digital Sidetone Volume", MAX9867_SIDETONE, 0, 31, 1), SOC_SINGLE_TLV("Digital Playback Volume", MAX9867_DACLEVEL, 0, 15, 1, max9867_dac_tlv), From 0e0e10fde0e9808d1991268f5dca69fb36c025f7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 May 2020 09:24:16 +0200 Subject: [PATCH 303/428] ASoC: Intel: bytcr_rt5640: Add quirk for Toshiba Encore WT8-A tablet The Toshiba Encore WT8-A tablet almost fully works with the default settings for non-CR Bay Trail devices. The only problem is that its jack-detect switch is not inverted (it is active high instead of the normal active low). Add a quirk for this model using the default settings + BYT_RT5640_JD_NOT_INV. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518072416.5348-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 08f4ae964b02..fbfd53874b47 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -742,6 +742,18 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { /* Toshiba Encore WT8-A */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT8-A"), + }, + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_JD_NOT_INV | + BYT_RT5640_MCLK_EN), + }, { /* Catch-all for generic Insyde tablets, must be last */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), From 9b5e98e21467cd0a6c689db5ef971d7a61c73929 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:51 +0800 Subject: [PATCH 304/428] ASoC: amd: add Renoir ACP3x IP register header Add register header for ACP3x IP in Renoir platform. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/rn_chip_offset_byte.h | 349 +++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 sound/soc/amd/renoir/rn_chip_offset_byte.h diff --git a/sound/soc/amd/renoir/rn_chip_offset_byte.h b/sound/soc/amd/renoir/rn_chip_offset_byte.h new file mode 100644 index 000000000000..d20d967b5ff9 --- /dev/null +++ b/sound/soc/amd/renoir/rn_chip_offset_byte.h @@ -0,0 +1,349 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ACP 3.1 Register Documentation + * + * Copyright 2020 Advanced Micro Devices, Inc. + */ + +#ifndef _rn_OFFSET_HEADER +#define _rn_OFFSET_HEADER +// Registers from ACP_DMA block + +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_CNTL_1 0x1240004 +#define ACP_DMA_CNTL_2 0x1240008 +#define ACP_DMA_CNTL_3 0x124000C +#define ACP_DMA_CNTL_4 0x1240010 +#define ACP_DMA_CNTL_5 0x1240014 +#define ACP_DMA_CNTL_6 0x1240018 +#define ACP_DMA_CNTL_7 0x124001C +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_STRT_IDX_1 0x1240024 +#define ACP_DMA_DSCR_STRT_IDX_2 0x1240028 +#define ACP_DMA_DSCR_STRT_IDX_3 0x124002C +#define ACP_DMA_DSCR_STRT_IDX_4 0x1240030 +#define ACP_DMA_DSCR_STRT_IDX_5 0x1240034 +#define ACP_DMA_DSCR_STRT_IDX_6 0x1240038 +#define ACP_DMA_DSCR_STRT_IDX_7 0x124003C +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_DSCR_CNT_1 0x1240044 +#define ACP_DMA_DSCR_CNT_2 0x1240048 +#define ACP_DMA_DSCR_CNT_3 0x124004C +#define ACP_DMA_DSCR_CNT_4 0x1240050 +#define ACP_DMA_DSCR_CNT_5 0x1240054 +#define ACP_DMA_DSCR_CNT_6 0x1240058 +#define ACP_DMA_DSCR_CNT_7 0x124005C +#define ACP_DMA_PRIO_0 0x1240060 +#define ACP_DMA_PRIO_1 0x1240064 +#define ACP_DMA_PRIO_2 0x1240068 +#define ACP_DMA_PRIO_3 0x124006C +#define ACP_DMA_PRIO_4 0x1240070 +#define ACP_DMA_PRIO_5 0x1240074 +#define ACP_DMA_PRIO_6 0x1240078 +#define ACP_DMA_PRIO_7 0x124007C +#define ACP_DMA_CUR_DSCR_0 0x1240080 +#define ACP_DMA_CUR_DSCR_1 0x1240084 +#define ACP_DMA_CUR_DSCR_2 0x1240088 +#define ACP_DMA_CUR_DSCR_3 0x124008C +#define ACP_DMA_CUR_DSCR_4 0x1240090 +#define ACP_DMA_CUR_DSCR_5 0x1240094 +#define ACP_DMA_CUR_DSCR_6 0x1240098 +#define ACP_DMA_CUR_DSCR_7 0x124009C +#define ACP_DMA_CUR_TRANS_CNT_0 0x12400A0 +#define ACP_DMA_CUR_TRANS_CNT_1 0x12400A4 +#define ACP_DMA_CUR_TRANS_CNT_2 0x12400A8 +#define ACP_DMA_CUR_TRANS_CNT_3 0x12400AC +#define ACP_DMA_CUR_TRANS_CNT_4 0x12400B0 +#define ACP_DMA_CUR_TRANS_CNT_5 0x12400B4 +#define ACP_DMA_CUR_TRANS_CNT_6 0x12400B8 +#define ACP_DMA_CUR_TRANS_CNT_7 0x12400BC +#define ACP_DMA_ERR_STS_0 0x12400C0 +#define ACP_DMA_ERR_STS_1 0x12400C4 +#define ACP_DMA_ERR_STS_2 0x12400C8 +#define ACP_DMA_ERR_STS_3 0x12400CC +#define ACP_DMA_ERR_STS_4 0x12400D0 +#define ACP_DMA_ERR_STS_5 0x12400D4 +#define ACP_DMA_ERR_STS_6 0x12400D8 +#define ACP_DMA_ERR_STS_7 0x12400DC +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 +#define ACP_DMA_CH_GROUP 0x12400EC +#define ACP_DMA_CH_RST_STS 0x12400F0 + +// Registers from ACP_AXI2AXIATU block + +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C +#define ACPAXI2AXI_ATU_CTRL 0x1240C40 + +// Registers from ACP_CLKRST block + +#define ACP_SOFT_RESET 0x1241000 +#define ACP_CONTROL 0x1241004 +#define ACP_STATUS 0x1241008 +#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010 + +// Registers from ACP_MISC block + +#define ACP_EXTERNAL_INTR_ENB 0x1241800 +#define ACP_EXTERNAL_INTR_CNTL 0x1241804 +#define ACP_EXTERNAL_INTR_STAT 0x1241808 +#define ACP_PGMEM_CTRL 0x12418C0 +#define ACP_ERROR_STATUS 0x12418C4 +#define ACP_SW_I2S_ERROR_REASON 0x12418C8 +#define ACP_MEM_PG_STS 0x12418CC + +// Registers from ACP_PGFSM block + +#define ACP_I2S_PIN_CONFIG 0x1241400 +#define ACP_PAD_PULLUP_PULLDOWN_CTRL 0x1241404 +#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x1241408 +#define ACP_SW_PAD_KEEPER_EN 0x124140C +#define ACP_PGFSM_CONTROL 0x124141C +#define ACP_PGFSM_STATUS 0x1241420 +#define ACP_CLKMUX_SEL 0x1241424 +#define ACP_DEVICE_STATE 0x1241428 +#define AZ_DEVICE_STATE 0x124142C +#define ACP_INTR_URGENCY_TIMER 0x1241430 +#define AZ_INTR_URGENCY_TIMER 0x1241434 + +// Registers from ACP_SCRATCH block + +#define ACP_SCRATCH_REG_0 0x1250000 +#define ACP_SCRATCH_REG_1 0x1250004 +#define ACP_SCRATCH_REG_2 0x1250008 +#define ACP_SCRATCH_REG_3 0x125000C +#define ACP_SCRATCH_REG_4 0x1250010 +#define ACP_SCRATCH_REG_5 0x1250014 +#define ACP_SCRATCH_REG_6 0x1250018 +#define ACP_SCRATCH_REG_7 0x125001C +#define ACP_SCRATCH_REG_8 0x1250020 +#define ACP_SCRATCH_REG_9 0x1250024 +#define ACP_SCRATCH_REG_10 0x1250028 +#define ACP_SCRATCH_REG_11 0x125002C +#define ACP_SCRATCH_REG_12 0x1250030 +#define ACP_SCRATCH_REG_13 0x1250034 +#define ACP_SCRATCH_REG_14 0x1250038 +#define ACP_SCRATCH_REG_15 0x125003C +#define ACP_SCRATCH_REG_16 0x1250040 +#define ACP_SCRATCH_REG_17 0x1250044 +#define ACP_SCRATCH_REG_18 0x1250048 +#define ACP_SCRATCH_REG_19 0x125004C +#define ACP_SCRATCH_REG_20 0x1250050 +#define ACP_SCRATCH_REG_21 0x1250054 +#define ACP_SCRATCH_REG_22 0x1250058 +#define ACP_SCRATCH_REG_23 0x125005C +#define ACP_SCRATCH_REG_24 0x1250060 +#define ACP_SCRATCH_REG_25 0x1250064 +#define ACP_SCRATCH_REG_26 0x1250068 +#define ACP_SCRATCH_REG_27 0x125006C +#define ACP_SCRATCH_REG_28 0x1250070 +#define ACP_SCRATCH_REG_29 0x1250074 +#define ACP_SCRATCH_REG_30 0x1250078 +#define ACP_SCRATCH_REG_31 0x125007C +#define ACP_SCRATCH_REG_32 0x1250080 +#define ACP_SCRATCH_REG_33 0x1250084 +#define ACP_SCRATCH_REG_34 0x1250088 +#define ACP_SCRATCH_REG_35 0x125008C +#define ACP_SCRATCH_REG_36 0x1250090 +#define ACP_SCRATCH_REG_37 0x1250094 +#define ACP_SCRATCH_REG_38 0x1250098 +#define ACP_SCRATCH_REG_39 0x125009C +#define ACP_SCRATCH_REG_40 0x12500A0 +#define ACP_SCRATCH_REG_41 0x12500A4 +#define ACP_SCRATCH_REG_42 0x12500A8 +#define ACP_SCRATCH_REG_43 0x12500AC +#define ACP_SCRATCH_REG_44 0x12500B0 +#define ACP_SCRATCH_REG_45 0x12500B4 +#define ACP_SCRATCH_REG_46 0x12500B8 +#define ACP_SCRATCH_REG_47 0x12500BC +#define ACP_SCRATCH_REG_48 0x12500C0 +#define ACP_SCRATCH_REG_49 0x12500C4 +#define ACP_SCRATCH_REG_50 0x12500C8 +#define ACP_SCRATCH_REG_51 0x12500CC +#define ACP_SCRATCH_REG_52 0x12500D0 +#define ACP_SCRATCH_REG_53 0x12500D4 +#define ACP_SCRATCH_REG_54 0x12500D8 +#define ACP_SCRATCH_REG_55 0x12500DC +#define ACP_SCRATCH_REG_56 0x12500E0 +#define ACP_SCRATCH_REG_57 0x12500E4 +#define ACP_SCRATCH_REG_58 0x12500E8 +#define ACP_SCRATCH_REG_59 0x12500EC +#define ACP_SCRATCH_REG_60 0x12500F0 +#define ACP_SCRATCH_REG_61 0x12500F4 +#define ACP_SCRATCH_REG_62 0x12500F8 +#define ACP_SCRATCH_REG_63 0x12500FC +#define ACP_SCRATCH_REG_64 0x1250100 +#define ACP_SCRATCH_REG_65 0x1250104 +#define ACP_SCRATCH_REG_66 0x1250108 +#define ACP_SCRATCH_REG_67 0x125010C +#define ACP_SCRATCH_REG_68 0x1250110 +#define ACP_SCRATCH_REG_69 0x1250114 +#define ACP_SCRATCH_REG_70 0x1250118 +#define ACP_SCRATCH_REG_71 0x125011C +#define ACP_SCRATCH_REG_72 0x1250120 +#define ACP_SCRATCH_REG_73 0x1250124 +#define ACP_SCRATCH_REG_74 0x1250128 +#define ACP_SCRATCH_REG_75 0x125012C +#define ACP_SCRATCH_REG_76 0x1250130 +#define ACP_SCRATCH_REG_77 0x1250134 +#define ACP_SCRATCH_REG_78 0x1250138 +#define ACP_SCRATCH_REG_79 0x125013C +#define ACP_SCRATCH_REG_80 0x1250140 +#define ACP_SCRATCH_REG_81 0x1250144 +#define ACP_SCRATCH_REG_82 0x1250148 +#define ACP_SCRATCH_REG_83 0x125014C +#define ACP_SCRATCH_REG_84 0x1250150 +#define ACP_SCRATCH_REG_85 0x1250154 +#define ACP_SCRATCH_REG_86 0x1250158 +#define ACP_SCRATCH_REG_87 0x125015C +#define ACP_SCRATCH_REG_88 0x1250160 +#define ACP_SCRATCH_REG_89 0x1250164 +#define ACP_SCRATCH_REG_90 0x1250168 +#define ACP_SCRATCH_REG_91 0x125016C +#define ACP_SCRATCH_REG_92 0x1250170 +#define ACP_SCRATCH_REG_93 0x1250174 +#define ACP_SCRATCH_REG_94 0x1250178 +#define ACP_SCRATCH_REG_95 0x125017C +#define ACP_SCRATCH_REG_96 0x1250180 +#define ACP_SCRATCH_REG_97 0x1250184 +#define ACP_SCRATCH_REG_98 0x1250188 +#define ACP_SCRATCH_REG_99 0x125018C +#define ACP_SCRATCH_REG_100 0x1250190 +#define ACP_SCRATCH_REG_101 0x1250194 +#define ACP_SCRATCH_REG_102 0x1250198 +#define ACP_SCRATCH_REG_103 0x125019C +#define ACP_SCRATCH_REG_104 0x12501A0 +#define ACP_SCRATCH_REG_105 0x12501A4 +#define ACP_SCRATCH_REG_106 0x12501A8 +#define ACP_SCRATCH_REG_107 0x12501AC +#define ACP_SCRATCH_REG_108 0x12501B0 +#define ACP_SCRATCH_REG_109 0x12501B4 +#define ACP_SCRATCH_REG_110 0x12501B8 +#define ACP_SCRATCH_REG_111 0x12501BC +#define ACP_SCRATCH_REG_112 0x12501C0 +#define ACP_SCRATCH_REG_113 0x12501C4 +#define ACP_SCRATCH_REG_114 0x12501C8 +#define ACP_SCRATCH_REG_115 0x12501CC +#define ACP_SCRATCH_REG_116 0x12501D0 +#define ACP_SCRATCH_REG_117 0x12501D4 +#define ACP_SCRATCH_REG_118 0x12501D8 +#define ACP_SCRATCH_REG_119 0x12501DC +#define ACP_SCRATCH_REG_120 0x12501E0 +#define ACP_SCRATCH_REG_121 0x12501E4 +#define ACP_SCRATCH_REG_122 0x12501E8 +#define ACP_SCRATCH_REG_123 0x12501EC +#define ACP_SCRATCH_REG_124 0x12501F0 +#define ACP_SCRATCH_REG_125 0x12501F4 +#define ACP_SCRATCH_REG_126 0x12501F8 +#define ACP_SCRATCH_REG_127 0x12501FC +#define ACP_SCRATCH_REG_128 0x1250200 + +// Registers from ACP_AUDIO_BUFFERS block + +#define ACP_I2S_RX_RINGBUFADDR 0x1242000 +#define ACP_I2S_RX_RINGBUFSIZE 0x1242004 +#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008 +#define ACP_I2S_RX_FIFOADDR 0x124200C +#define ACP_I2S_RX_FIFOSIZE 0x1242010 +#define ACP_I2S_RX_DMA_SIZE 0x1242014 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1242018 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x124201C +#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020 +#define ACP_I2S_TX_RINGBUFADDR 0x1242024 +#define ACP_I2S_TX_RINGBUFSIZE 0x1242028 +#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C +#define ACP_I2S_TX_FIFOADDR 0x1242030 +#define ACP_I2S_TX_FIFOSIZE 0x1242034 +#define ACP_I2S_TX_DMA_SIZE 0x1242038 +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x124203C +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1242040 +#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044 +#define ACP_BT_RX_RINGBUFADDR 0x1242048 +#define ACP_BT_RX_RINGBUFSIZE 0x124204C +#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050 +#define ACP_BT_RX_FIFOADDR 0x1242054 +#define ACP_BT_RX_FIFOSIZE 0x1242058 +#define ACP_BT_RX_DMA_SIZE 0x124205C +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1242060 +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x1242064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define ACP_BT_TX_RINGBUFADDR 0x124206C +#define ACP_BT_TX_RINGBUFSIZE 0x1242070 +#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074 +#define ACP_BT_TX_FIFOADDR 0x1242078 +#define ACP_BT_TX_FIFOSIZE 0x124207C +#define ACP_BT_TX_DMA_SIZE 0x1242080 +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1242084 +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x1242088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C +#define ACP_HS_RX_RINGBUFADDR 0x1242090 +#define ACP_HS_RX_RINGBUFSIZE 0x1242094 +#define ACP_HS_RX_LINKPOSITIONCNTR 0x1242098 +#define ACP_HS_RX_FIFOADDR 0x124209C +#define ACP_HS_RX_FIFOSIZE 0x12420A0 +#define ACP_HS_RX_DMA_SIZE 0x12420A4 +#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x12420A8 +#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x12420AC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0 +#define ACP_HS_TX_RINGBUFADDR 0x12420B4 +#define ACP_HS_TX_RINGBUFSIZE 0x12420B8 +#define ACP_HS_TX_LINKPOSITIONCNTR 0x12420BC +#define ACP_HS_TX_FIFOADDR 0x12420C0 +#define ACP_HS_TX_FIFOSIZE 0x12420C4 +#define ACP_HS_TX_DMA_SIZE 0x12420C8 +#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x12420CC +#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x12420D0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4 + +// Registers from ACP_I2S_TDM block + +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 + +// Registers from ACP_BT_TDM block + +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_RXFRMT 0x1242808 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_BTTDM_TXFRMT 0x1242810 + +// Registers from ACP_WOV block + +#define ACP_WOV_PDM_ENABLE 0x1242C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x1242C08 +#define ACP_WOV_RX_RINGBUFADDR 0x1242C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x1242C10 +#define ACP_WOV_RX_LINKPOSITIONCNTR 0x1242C14 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x1242C18 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x1242C1C +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x1242C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x1242C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x1242C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x1242C2C +#define ACP_WOV_PDM_VAD_CTRL 0x1242C30 +#define ACP_WOV_BUFFER_STATUS 0x1242C58 +#define ACP_WOV_MISC_CTRL 0x1242C5C +#define ACP_WOV_CLK_CTRL 0x1242C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x1242C64 +#define ACP_WOV_ERROR_STATUS_REGISTER 0x1242C68 +#endif From 1eb2852efe05abfa94cd78cc9865389643726ee9 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:52 +0800 Subject: [PATCH 305/428] ASoC: amd: add Renoir ACP PCI driver ACP is a PCI audio device. This patch adds PCI driver to bind to this device and get PCI resources. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/rn-pci-acp3x.c | 87 +++++++++++++++++++++++++++++ sound/soc/amd/renoir/rn_acp3x.h | 21 +++++++ 2 files changed, 108 insertions(+) create mode 100644 sound/soc/amd/renoir/rn-pci-acp3x.c create mode 100644 sound/soc/amd/renoir/rn_acp3x.h diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c new file mode 100644 index 000000000000..56b76e355cd4 --- /dev/null +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD Renoir ACP PCI Driver +// +//Copyright 2020 Advanced Micro Devices, Inc. + +#include +#include +#include + +#include "rn_acp3x.h" + +struct acp_dev_data { + void __iomem *acp_base; +}; + +static int snd_rn_acp_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp_dev_data *adata; + int ret; + u32 addr; + + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP3x audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + + adata = devm_kzalloc(&pci->dev, sizeof(struct acp_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + + addr = pci_resource_start(pci, 0); + adata->acp_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp_base) { + ret = -ENOMEM; + goto release_regions; + } + pci_set_master(pci); + pci_set_drvdata(pci, adata); + return 0; + +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static void snd_rn_acp_remove(struct pci_dev *pci) +{ + pci_disable_msi(pci); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_rn_acp_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_rn_acp_ids); + +static struct pci_driver rn_acp_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_rn_acp_ids, + .probe = snd_rn_acp_probe, + .remove = snd_rn_acp_remove, +}; + +module_pci_driver(rn_acp_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP Renoir PCI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h new file mode 100644 index 000000000000..da5715759646 --- /dev/null +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ALSA SoC PDM Driver + * + * Copyright 2020 Advanced Micro Devices, Inc. + */ + +#include "rn_chip_offset_byte.h" + +#define ACP_PHY_BASE_ADDRESS 0x1240000 +#define ACP_DEVICE_ID 0x15E2 + +static inline u32 rn_readl(void __iomem *base_addr) +{ + return readl(base_addr - ACP_PHY_BASE_ADDRESS); +} + +static inline void rn_writel(u32 val, void __iomem *base_addr) +{ + writel(val, base_addr - ACP_PHY_BASE_ADDRESS); +} From 85ded495640e63282aa83583ab64304a9912303d Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:53 +0800 Subject: [PATCH 306/428] ASoC: amd: add acp init/de-init functions Add Renoir ACP PCI driver init/deinit functions. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-4-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/rn-pci-acp3x.c | 143 ++++++++++++++++++++++++++++ sound/soc/amd/renoir/rn_acp3x.h | 16 ++++ 2 files changed, 159 insertions(+) diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index 56b76e355cd4..429813f6ba1c 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -7,13 +7,146 @@ #include #include #include +#include #include "rn_acp3x.h" +static int acp_power_gating; +module_param(acp_power_gating, int, 0644); +MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating"); + struct acp_dev_data { void __iomem *acp_base; }; +static int rn_acp_power_on(void __iomem *acp_base) +{ + u32 val; + int timeout; + + val = rn_readl(acp_base + ACP_PGFSM_STATUS); + + if (val == 0) + return val; + + if ((val & ACP_PGFSM_STATUS_MASK) != + ACP_POWER_ON_IN_PROGRESS) + rn_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, + acp_base + ACP_PGFSM_CONTROL); + timeout = 0; + while (++timeout < 500) { + val = rn_readl(acp_base + ACP_PGFSM_STATUS); + if (!val) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int rn_acp_power_off(void __iomem *acp_base) +{ + u32 val; + int timeout; + + rn_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK, + acp_base + ACP_PGFSM_CONTROL); + timeout = 0; + while (++timeout < 500) { + val = rn_readl(acp_base + ACP_PGFSM_STATUS); + if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int rn_acp_reset(void __iomem *acp_base) +{ + u32 val; + int timeout; + + rn_writel(1, acp_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = rn_readl(acp_base + ACP_SOFT_RESET); + if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) + break; + cpu_relax(); + } + rn_writel(0, acp_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = rn_readl(acp_base + ACP_SOFT_RESET); + if (!val) + return 0; + cpu_relax(); + } + return -ETIMEDOUT; +} + +static void rn_acp_enable_interrupts(void __iomem *acp_base) +{ + u32 ext_intr_ctrl; + + rn_writel(0x01, acp_base + ACP_EXTERNAL_INTR_ENB); + ext_intr_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_ctrl |= ACP_ERROR_MASK; + rn_writel(ext_intr_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void rn_acp_disable_interrupts(void __iomem *acp_base) +{ + rn_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + + ACP_EXTERNAL_INTR_STAT); + rn_writel(0x00, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static int rn_acp_init(void __iomem *acp_base) +{ + int ret; + + /* power on */ + ret = rn_acp_power_on(acp_base); + if (ret) { + pr_err("ACP power on failed\n"); + return ret; + } + rn_writel(0x01, acp_base + ACP_CONTROL); + /* Reset */ + ret = rn_acp_reset(acp_base); + if (ret) { + pr_err("ACP reset failed\n"); + return ret; + } + rn_writel(0x03, acp_base + ACP_CLKMUX_SEL); + rn_acp_enable_interrupts(acp_base); + return 0; +} + +static int rn_acp_deinit(void __iomem *acp_base) +{ + int ret; + + rn_acp_disable_interrupts(acp_base); + /* Reset */ + ret = rn_acp_reset(acp_base); + if (ret) { + pr_err("ACP reset failed\n"); + return ret; + } + rn_writel(0x00, acp_base + ACP_CLKMUX_SEL); + rn_writel(0x00, acp_base + ACP_CONTROL); + /* power off */ + if (acp_power_gating) { + ret = rn_acp_power_off(acp_base); + if (ret) { + pr_err("ACP power off failed\n"); + return ret; + } + } + return 0; +} + static int snd_rn_acp_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -48,6 +181,9 @@ static int snd_rn_acp_probe(struct pci_dev *pci, } pci_set_master(pci); pci_set_drvdata(pci, adata); + ret = rn_acp_init(adata->acp_base); + if (ret) + goto release_regions; return 0; release_regions: @@ -60,6 +196,13 @@ disable_pci: static void snd_rn_acp_remove(struct pci_dev *pci) { + struct acp_dev_data *adata; + int ret; + + adata = pci_get_drvdata(pci); + ret = rn_acp_deinit(adata->acp_base); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); pci_disable_msi(pci); pci_release_regions(pci); pci_disable_device(pci); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index da5715759646..ec2a85085163 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -9,6 +9,22 @@ #define ACP_PHY_BASE_ADDRESS 0x1240000 #define ACP_DEVICE_ID 0x15E2 +#define ACP_POWER_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWER_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 +#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 + +#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 +#define ACP_PGFSM_STATUS_MASK 0x03 +#define ACP_POWERED_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWERED_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 + +#define ACP_ERROR_MASK 0x20000000 +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF static inline u32 rn_readl(void __iomem *base_addr) { From 66c4f558aa3a1b6f2b90981c364173af2f3d2c33 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:54 +0800 Subject: [PATCH 307/428] ASoC: amd: create acp3x pdm platform device ACP 3x IP has PDM decoder as one of IP blocks. Create a platform device for it, so that the PDM platform driver can be bound to this device. Pass PCI resources like MMIO, irq to this platform device. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-5-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/rn-pci-acp3x.c | 61 ++++++++++++++++++++++++++++- sound/soc/amd/renoir/rn_acp3x.h | 3 ++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index 429813f6ba1c..362409ef0d85 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "rn_acp3x.h" @@ -17,6 +19,8 @@ MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating"); struct acp_dev_data { void __iomem *acp_base; + struct resource *res; + struct platform_device *pdev; }; static int rn_acp_power_on(void __iomem *acp_base) @@ -151,6 +155,8 @@ static int snd_rn_acp_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { struct acp_dev_data *adata; + struct platform_device_info pdevinfo; + unsigned int irqflags; int ret; u32 addr; @@ -172,20 +178,70 @@ static int snd_rn_acp_probe(struct pci_dev *pci, goto release_regions; } + /* check for msi interrupt support */ + ret = pci_enable_msi(pci); + if (ret) + /* msi is not enabled */ + irqflags = IRQF_SHARED; + else + /* msi is enabled */ + irqflags = 0; + addr = pci_resource_start(pci, 0); adata->acp_base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0)); if (!adata->acp_base) { ret = -ENOMEM; - goto release_regions; + goto disable_msi; } pci_set_master(pci); pci_set_drvdata(pci, adata); ret = rn_acp_init(adata->acp_base); if (ret) - goto release_regions; + goto disable_msi; + + adata->res = devm_kzalloc(&pci->dev, + sizeof(struct resource) * 2, + GFP_KERNEL); + if (!adata->res) { + ret = -ENOMEM; + goto de_init; + } + + adata->res[0].name = "acp_pdm_iomem"; + adata->res[0].flags = IORESOURCE_MEM; + adata->res[0].start = addr; + adata->res[0].end = addr + (ACP_REG_END - ACP_REG_START); + adata->res[1].name = "acp_pdm_irq"; + adata->res[1].flags = IORESOURCE_IRQ; + adata->res[1].start = pci->irq; + adata->res[1].end = pci->irq; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.name = "acp_rn_pdm_dma"; + pdevinfo.id = 0; + pdevinfo.parent = &pci->dev; + pdevinfo.num_res = 2; + pdevinfo.res = adata->res; + pdevinfo.data = &irqflags; + pdevinfo.size_data = sizeof(irqflags); + + adata->pdev = platform_device_register_full(&pdevinfo); + if (IS_ERR(adata->pdev)) { + dev_err(&pci->dev, "cannot register %s device\n", + pdevinfo.name); + ret = PTR_ERR(adata->pdev); + goto unregister_devs; + } return 0; +unregister_devs: + platform_device_unregister(adata->pdev); +de_init: + if (rn_acp_deinit(adata->acp_base)) + dev_err(&pci->dev, "ACP de-init failed\n"); +disable_msi: + pci_disable_msi(pci); release_regions: pci_release_regions(pci); disable_pci: @@ -200,6 +256,7 @@ static void snd_rn_acp_remove(struct pci_dev *pci) int ret; adata = pci_get_drvdata(pci); + platform_device_unregister(adata->pdev); ret = rn_acp_deinit(adata->acp_base); if (ret) dev_err(&pci->dev, "ACP de-init failed\n"); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index ec2a85085163..5e4fd99397d5 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -8,6 +8,9 @@ #include "rn_chip_offset_byte.h" #define ACP_PHY_BASE_ADDRESS 0x1240000 +#define ACP_REG_START 0x1240000 +#define ACP_REG_END 0x1250200 + #define ACP_DEVICE_ID 0x15E2 #define ACP_POWER_ON 0x00 #define ACP_POWER_ON_IN_PROGRESS 0x01 From f621a3676d3f52fcb8b7d8db8acbcc28423bcdb7 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:55 +0800 Subject: [PATCH 308/428] ASoC: amd: add ACP3x PDM platform driver PDM platform driver binds to the platform device created by ACP3x PCI device. PDM driver registers ALSA DMA and CPU DAI components with ASoC framework. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-6-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 95 ++++++++++++++++++++++++++++ sound/soc/amd/renoir/rn_acp3x.h | 5 ++ 2 files changed, 100 insertions(+) create mode 100644 sound/soc/amd/renoir/acp3x-pdm-dma.c diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c new file mode 100644 index 000000000000..1dda8cf2edd2 --- /dev/null +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ALSA SoC PDM Driver +// +//Copyright 2020 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include + +#include "rn_acp3x.h" + +#define DRV_NAME "acp_rn_pdm_dma" + +static struct snd_soc_dai_driver acp_pdm_dai_driver = { + .capture = { + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 48000, + .rate_max = 48000, + }, +}; + +static const struct snd_soc_component_driver acp_pdm_component = { + .name = DRV_NAME, +}; + +static int acp_pdm_audio_probe(struct platform_device *pdev) +{ + struct resource *res; + struct pdm_dev_data *adata; + unsigned int irqflags; + int status; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "platform_data not retrieved\n"); + return -ENODEV; + } + irqflags = *((unsigned int *)(pdev->dev.platform_data)); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENODEV; + } + + adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL); + if (!adata) + return -ENOMEM; + + adata->acp_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!adata->acp_base) + return -ENOMEM; + + adata->capture_stream = NULL; + + dev_set_drvdata(&pdev->dev, adata); + status = devm_snd_soc_register_component(&pdev->dev, + &acp_pdm_component, + &acp_pdm_dai_driver, 1); + if (status) { + dev_err(&pdev->dev, "Fail to register acp pdm dai\n"); + + return -ENODEV; + } + return 0; +} + +static int acp_pdm_audio_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver acp_pdm_dma_driver = { + .probe = acp_pdm_audio_probe, + .remove = acp_pdm_audio_remove, + .driver = { + .name = "acp_rn_pdm_dma", + }, +}; + +module_platform_driver(acp_pdm_dma_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP3x Renior PDM Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index 5e4fd99397d5..0b450882c6c4 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -29,6 +29,11 @@ #define ACP_ERROR_MASK 0x20000000 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF +struct pdm_dev_data { + void __iomem *acp_base; + struct snd_pcm_substream *capture_stream; +}; + static inline u32 rn_readl(void __iomem *base_addr) { return readl(base_addr - ACP_PHY_BASE_ADDRESS); From b9901654a90a367a74c34c76e0c8b4156bf539af Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:56 +0800 Subject: [PATCH 309/428] ASoC: amd: irq handler changes for ACP3x PDM dma driver Whenever audio data equal to the PDM watermark level are consumed, interrupt is generated. Acknowledge the interrupt. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-7-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 38 ++++++++++++++++++++++++++++ sound/soc/amd/renoir/rn_acp3x.h | 2 ++ 2 files changed, 40 insertions(+) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 1dda8cf2edd2..fdac2c1e3acd 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -16,6 +16,31 @@ #define DRV_NAME "acp_rn_pdm_dma" +static irqreturn_t pdm_irq_handler(int irq, void *dev_id) +{ + struct pdm_dev_data *rn_pdm_data; + u16 cap_flag; + u32 val; + + rn_pdm_data = dev_id; + if (!rn_pdm_data) + return IRQ_NONE; + + cap_flag = 0; + val = rn_readl(rn_pdm_data->acp_base + ACP_EXTERNAL_INTR_STAT); + if ((val & BIT(PDM_DMA_STAT)) && rn_pdm_data->capture_stream) { + rn_writel(BIT(PDM_DMA_STAT), rn_pdm_data->acp_base + + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(rn_pdm_data->capture_stream); + cap_flag = 1; + } + + if (cap_flag) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + static struct snd_soc_dai_driver acp_pdm_dai_driver = { .capture = { .rates = SNDRV_PCM_RATE_48000, @@ -60,6 +85,13 @@ static int acp_pdm_audio_probe(struct platform_device *pdev) if (!adata->acp_base) return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); + return -ENODEV; + } + + adata->pdm_irq = res->start; adata->capture_stream = NULL; dev_set_drvdata(&pdev->dev, adata); @@ -71,6 +103,12 @@ static int acp_pdm_audio_probe(struct platform_device *pdev) return -ENODEV; } + status = devm_request_irq(&pdev->dev, adata->pdm_irq, pdm_irq_handler, + irqflags, "ACP_PDM_IRQ", adata); + if (status) { + dev_err(&pdev->dev, "ACP PDM IRQ request failed\n"); + return -ENODEV; + } return 0; } diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index 0b450882c6c4..1ad8a7845fda 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -28,8 +28,10 @@ #define ACP_ERROR_MASK 0x20000000 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF +#define PDM_DMA_STAT 0x10 struct pdm_dev_data { + u32 pdm_irq; void __iomem *acp_base; struct snd_pcm_substream *capture_stream; }; From 4a767b1d039a855c491c4853013804323c06f728 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:57 +0800 Subject: [PATCH 310/428] ASoC: amd: add acp3x pdm driver dma ops This patch adds PDM driver DMA operations. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-8-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 195 +++++++++++++++++++++++++++ sound/soc/amd/renoir/rn_acp3x.h | 29 ++++ 2 files changed, 224 insertions(+) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index fdac2c1e3acd..8bb03fa5b4a5 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -16,6 +16,25 @@ #define DRV_NAME "acp_rn_pdm_dma" +static const struct snd_pcm_hardware acp_pdm_hardware_capture = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, + .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, + .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, + .periods_min = CAPTURE_MIN_NUM_PERIODS, + .periods_max = CAPTURE_MAX_NUM_PERIODS, +}; + static irqreturn_t pdm_irq_handler(int irq, void *dev_id) { struct pdm_dev_data *rn_pdm_data; @@ -41,6 +60,176 @@ static irqreturn_t pdm_irq_handler(int irq, void *dev_id) return IRQ_NONE; } +static void init_pdm_ring_buffer(u32 physical_addr, + u32 buffer_size, + u32 watermark_size, + void __iomem *acp_base) +{ + rn_writel(physical_addr, acp_base + ACP_WOV_RX_RINGBUFADDR); + rn_writel(buffer_size, acp_base + ACP_WOV_RX_RINGBUFSIZE); + rn_writel(watermark_size, acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE); + rn_writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL); +} + +static void enable_pdm_interrupts(void __iomem *acp_base) +{ + u32 ext_int_ctrl; + + ext_int_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_int_ctrl |= PDM_DMA_INTR_MASK; + rn_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void disable_pdm_interrupts(void __iomem *acp_base) +{ + u32 ext_int_ctrl; + + ext_int_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_int_ctrl |= ~PDM_DMA_INTR_MASK; + rn_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void config_acp_dma(struct pdm_stream_instance *rtd, int direction) +{ + u16 page_idx; + u32 low, high, val; + dma_addr_t addr; + + addr = rtd->dma_addr; + val = 0; + + /* Group Enable */ + rn_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp_base + + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + rn_writel(PAGE_SIZE_4K_ENABLE, rtd->acp_base + + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + + for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + rn_writel(low, rtd->acp_base + ACP_SCRATCH_REG_0 + val); + high |= BIT(31); + rn_writel(high, rtd->acp_base + ACP_SCRATCH_REG_0 + val + 4); + val += 8; + addr += PAGE_SIZE; + } +} + +static int acp_pdm_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct pdm_dev_data *adata; + struct pdm_stream_instance *pdm_data; + int ret; + + runtime = substream->runtime; + adata = dev_get_drvdata(component->dev); + pdm_data = kzalloc(sizeof(*pdm_data), GFP_KERNEL); + if (!pdm_data) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + runtime->hw = acp_pdm_hardware_capture; + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(pdm_data); + return ret; + } + + enable_pdm_interrupts(adata->acp_base); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + adata->capture_stream = substream; + + pdm_data->acp_base = adata->acp_base; + runtime->private_data = pdm_data; + return ret; +} + +static int acp_pdm_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct pdm_stream_instance *rtd; + size_t size, period_bytes; + + rtd = substream->runtime->private_data; + if (!rtd) + return -EINVAL; + size = params_buffer_bytes(params); + period_bytes = params_period_bytes(params); + rtd->dma_addr = substream->dma_buffer.addr; + rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + config_acp_dma(rtd, substream->stream); + init_pdm_ring_buffer(MEM_WINDOW_START, size, period_bytes, + rtd->acp_base); + return 0; +} + +static u64 acp_pdm_get_byte_count(struct pdm_stream_instance *rtd, + int direction) +{ + union acp_pdm_dma_count byte_count; + + byte_count.bcount.high = + rn_readl(rtd->acp_base + + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH); + byte_count.bcount.low = + rn_readl(rtd->acp_base + + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW); + return byte_count.bytescount; +} + +static snd_pcm_uframes_t acp_pdm_dma_pointer(struct snd_soc_component *comp, + struct snd_pcm_substream *stream) +{ + struct pdm_stream_instance *rtd; + u32 pos, buffersize; + u64 bytescount; + + rtd = stream->runtime->private_data; + buffersize = frames_to_bytes(stream->runtime, + stream->runtime->buffer_size); + bytescount = acp_pdm_get_byte_count(rtd, stream->stream); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + return bytes_to_frames(stream->runtime, pos); +} + +static int acp_pdm_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, MIN_BUFFER, MAX_BUFFER); + return 0; +} + +static int acp_pdm_dma_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + return snd_pcm_lib_default_mmap(substream, vma); +} + +static int acp_pdm_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct pdm_dev_data *adata = dev_get_drvdata(component->dev); + + disable_pdm_interrupts(adata->acp_base); + adata->capture_stream = NULL; + return 0; +} + static struct snd_soc_dai_driver acp_pdm_dai_driver = { .capture = { .rates = SNDRV_PCM_RATE_48000, @@ -55,6 +244,12 @@ static struct snd_soc_dai_driver acp_pdm_dai_driver = { static const struct snd_soc_component_driver acp_pdm_component = { .name = DRV_NAME, + .open = acp_pdm_dma_open, + .close = acp_pdm_dma_close, + .hw_params = acp_pdm_dma_hw_params, + .pointer = acp_pdm_dma_pointer, + .mmap = acp_pdm_dma_mmap, + .pcm_construct = acp_pdm_dma_new, }; static int acp_pdm_audio_probe(struct platform_device *pdev) diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index 1ad8a7845fda..3536d24374f3 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -29,13 +29,42 @@ #define ACP_ERROR_MASK 0x20000000 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF #define PDM_DMA_STAT 0x10 +#define PDM_DMA_INTR_MASK 0x10000 +#define ACP_ERROR_STAT 29 +#define ACP_SRAM_PTE_OFFSET 0x02050000 +#define PAGE_SIZE_4K_ENABLE 0x2 +#define MEM_WINDOW_START 0x4000000 + +#define CAPTURE_MIN_NUM_PERIODS 4 +#define CAPTURE_MAX_NUM_PERIODS 4 +#define CAPTURE_MAX_PERIOD_SIZE 8192 +#define CAPTURE_MIN_PERIOD_SIZE 4096 + +#define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS) +#define MIN_BUFFER MAX_BUFFER struct pdm_dev_data { u32 pdm_irq; void __iomem *acp_base; struct snd_pcm_substream *capture_stream; }; +struct pdm_stream_instance { + u16 num_pages; + u16 channels; + dma_addr_t dma_addr; + u64 bytescount; + void __iomem *acp_base; +}; + +union acp_pdm_dma_count { + struct { + u32 low; + u32 high; + } bcount; + u64 bytescount; +}; + static inline u32 rn_readl(void __iomem *base_addr) { return readl(base_addr - ACP_PHY_BASE_ADDRESS); From 370e7dde5b3d71820e142b566683306940daeffe Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:58 +0800 Subject: [PATCH 311/428] ASoC: amd: add ACP PDM DMA driver dai ops This patch adds ACP3x PDM DMA driver DAI operations. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-9-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 149 +++++++++++++++++++++++++++ sound/soc/amd/renoir/rn_acp3x.h | 9 ++ 2 files changed, 158 insertions(+) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 8bb03fa5b4a5..fd19b17f553e 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -71,6 +71,27 @@ static void init_pdm_ring_buffer(u32 physical_addr, rn_writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL); } +static void config_pdm_stream_params(unsigned int ch_mask, + void __iomem *acp_base) +{ + rn_writel(ch_mask, acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); + rn_writel(PDM_DECIMATION_FACTOR, acp_base + + ACP_WOV_PDM_DECIMATION_FACTOR); +} + +static void enable_pdm_clock(void __iomem *acp_base) +{ + u32 pdm_clk_enable, pdm_ctrl; + + pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK; + pdm_ctrl = 0x00; + + rn_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL); + pdm_ctrl = rn_readl(acp_base + ACP_WOV_MISC_CTRL); + pdm_ctrl |= ACP_WOV_MISC_CTRL_MASK; + rn_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL); +} + static void enable_pdm_interrupts(void __iomem *acp_base) { u32 ext_int_ctrl; @@ -89,6 +110,77 @@ static void disable_pdm_interrupts(void __iomem *acp_base) rn_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); } +static bool check_pdm_dma_status(void __iomem *acp_base) +{ + bool pdm_dma_status; + u32 pdm_enable, pdm_dma_enable; + + pdm_dma_status = false; + pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE); + pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_enable & ACP_PDM_ENABLE) && (pdm_dma_enable & + ACP_PDM_DMA_EN_STATUS)) + pdm_dma_status = true; + return pdm_dma_status; +} + +static int start_pdm_dma(void __iomem *acp_base) +{ + u32 pdm_enable; + u32 pdm_dma_enable; + int timeout; + + pdm_enable = 0x01; + pdm_dma_enable = 0x01; + + enable_pdm_clock(acp_base); + rn_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); + rn_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); + pdm_dma_enable = 0x00; + timeout = 0; + while (++timeout < ACP_COUNTER) { + pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_dma_enable & 0x02) == ACP_PDM_DMA_EN_STATUS) + return 0; + udelay(DELAY_US); + } + return -ETIMEDOUT; +} + +static int stop_pdm_dma(void __iomem *acp_base) +{ + u32 pdm_enable, pdm_dma_enable, pdm_fifo_flush; + int timeout; + + pdm_enable = 0x00; + pdm_dma_enable = 0x00; + pdm_fifo_flush = 0x00; + + pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE); + pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if (pdm_dma_enable & 0x01) { + pdm_dma_enable = 0x02; + rn_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); + pdm_dma_enable = 0x00; + timeout = 0; + while (++timeout < ACP_COUNTER) { + pdm_dma_enable = rn_readl(acp_base + + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_dma_enable & 0x02) == 0x00) + break; + udelay(DELAY_US); + } + if (timeout == ACP_COUNTER) + return -ETIMEDOUT; + } + if (pdm_enable == ACP_PDM_ENABLE) { + pdm_enable = ACP_PDM_DISABLE; + rn_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); + } + rn_writel(0x01, acp_base + ACP_WOV_PDM_FIFO_FLUSH); + return 0; +} + static void config_acp_dma(struct pdm_stream_instance *rtd, int direction) { u16 page_idx; @@ -230,6 +322,62 @@ static int acp_pdm_dma_close(struct snd_soc_component *component, return 0; } +static int acp_pdm_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct pdm_stream_instance *rtd; + unsigned int ch_mask; + + rtd = substream->runtime->private_data; + switch (params_channels(params)) { + case TWO_CH: + default: + ch_mask = 0x00; + break; + } + config_pdm_stream_params(ch_mask, rtd->acp_base); + return 0; +} + +static int acp_pdm_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct pdm_stream_instance *rtd; + int ret; + bool pdm_status; + + rtd = substream->runtime->private_data; + ret = 0; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + rtd->bytescount = acp_pdm_get_byte_count(rtd, + substream->stream); + pdm_status = check_pdm_dma_status(rtd->acp_base); + if (!pdm_status) + ret = start_pdm_dma(rtd->acp_base); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + pdm_status = check_pdm_dma_status(rtd->acp_base); + if (pdm_status) + ret = stop_pdm_dma(rtd->acp_base); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static struct snd_soc_dai_ops acp_pdm_dai_ops = { + .hw_params = acp_pdm_dai_hw_params, + .trigger = acp_pdm_dai_trigger, +}; + static struct snd_soc_dai_driver acp_pdm_dai_driver = { .capture = { .rates = SNDRV_PCM_RATE_48000, @@ -240,6 +388,7 @@ static struct snd_soc_dai_driver acp_pdm_dai_driver = { .rate_min = 48000, .rate_max = 48000, }, + .ops = &acp_pdm_dai_ops, }; static const struct snd_soc_component_driver acp_pdm_component = { diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index 3536d24374f3..a4f654cf2df0 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -31,6 +31,15 @@ #define PDM_DMA_STAT 0x10 #define PDM_DMA_INTR_MASK 0x10000 #define ACP_ERROR_STAT 29 +#define PDM_DECIMATION_FACTOR 0x2 +#define ACP_PDM_CLK_FREQ_MASK 0x07 +#define ACP_WOV_MISC_CTRL_MASK 0x10 +#define ACP_PDM_ENABLE 0x01 +#define ACP_PDM_DISABLE 0x00 +#define ACP_PDM_DMA_EN_STATUS 0x02 +#define TWO_CH 0x02 +#define DELAY_US 5 +#define ACP_COUNTER 20000 #define ACP_SRAM_PTE_OFFSET 0x02050000 #define PAGE_SIZE_4K_ENABLE 0x2 From c346e768f92cd6dbed474adf2f5eb3c9763a8bfa Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:16:59 +0800 Subject: [PATCH 312/428] ASoC: amd: add Renoir ACP PCI driver PM ops Add Renoir ACP Pci driver pm ops. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-10-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/rn-pci-acp3x.c | 46 +++++++++++++++++++++++++++++ sound/soc/amd/renoir/rn_acp3x.h | 2 ++ 2 files changed, 48 insertions(+) diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index 362409ef0d85..71bfae644372 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "rn_acp3x.h" @@ -233,6 +234,10 @@ static int snd_rn_acp_probe(struct pci_dev *pci, ret = PTR_ERR(adata->pdev); goto unregister_devs; } + pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); return 0; unregister_devs: @@ -250,6 +255,42 @@ disable_pci: return ret; } +static int snd_rn_acp_suspend(struct device *dev) +{ + int ret; + struct acp_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = rn_acp_deinit(adata->acp_base); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + else + dev_dbg(dev, "ACP de-initialized\n"); + + return 0; +} + +static int snd_rn_acp_resume(struct device *dev) +{ + int ret; + struct acp_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = rn_acp_init(adata->acp_base); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static const struct dev_pm_ops rn_acp_pm = { + .runtime_suspend = snd_rn_acp_suspend, + .runtime_resume = snd_rn_acp_resume, + .suspend = snd_rn_acp_suspend, + .resume = snd_rn_acp_resume, +}; + static void snd_rn_acp_remove(struct pci_dev *pci) { struct acp_dev_data *adata; @@ -260,6 +301,8 @@ static void snd_rn_acp_remove(struct pci_dev *pci) ret = rn_acp_deinit(adata->acp_base); if (ret) dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); pci_disable_msi(pci); pci_release_regions(pci); pci_disable_device(pci); @@ -278,6 +321,9 @@ static struct pci_driver rn_acp_driver = { .id_table = snd_rn_acp_ids, .probe = snd_rn_acp_probe, .remove = snd_rn_acp_remove, + .driver = { + .pm = &rn_acp_pm, + } }; module_pci_driver(rn_acp_driver); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index a4f654cf2df0..6e1888167fb3 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -40,6 +40,8 @@ #define TWO_CH 0x02 #define DELAY_US 5 #define ACP_COUNTER 20000 +/* time in ms for runtime suspend delay */ +#define ACP_SUSPEND_DELAY_MS 2000 #define ACP_SRAM_PTE_OFFSET 0x02050000 #define PAGE_SIZE_4K_ENABLE 0x2 From 35e4be1136e69710ffe559d173c9d66ff7d32730 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:17:00 +0800 Subject: [PATCH 313/428] ASoC: amd: add ACP PDM DMA driver pm ops Add ACP PDM DMA driver pm ops. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-11-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index fd19b17f553e..942010021319 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -453,19 +454,71 @@ static int acp_pdm_audio_probe(struct platform_device *pdev) dev_err(&pdev->dev, "ACP PDM IRQ request failed\n"); return -ENODEV; } + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + pm_runtime_allow(&pdev->dev); return 0; } static int acp_pdm_audio_remove(struct platform_device *pdev) { + pm_runtime_disable(&pdev->dev); return 0; } +static int acp_pdm_resume(struct device *dev) +{ + struct pdm_dev_data *adata; + struct snd_pcm_runtime *runtime; + struct pdm_stream_instance *rtd; + u32 period_bytes, buffer_len; + + adata = dev_get_drvdata(dev); + if (adata->capture_stream && adata->capture_stream->runtime) { + runtime = adata->capture_stream->runtime; + rtd = runtime->private_data; + period_bytes = frames_to_bytes(runtime, runtime->period_size); + buffer_len = frames_to_bytes(runtime, runtime->buffer_size); + config_acp_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); + init_pdm_ring_buffer(MEM_WINDOW_START, buffer_len, period_bytes, + adata->acp_base); + } + enable_pdm_interrupts(adata->acp_base); + return 0; +} + +static int acp_pdm_runtime_suspend(struct device *dev) +{ + struct pdm_dev_data *adata; + + adata = dev_get_drvdata(dev); + disable_pdm_interrupts(adata->acp_base); + + return 0; +} + +static int acp_pdm_runtime_resume(struct device *dev) +{ + struct pdm_dev_data *adata; + + adata = dev_get_drvdata(dev); + enable_pdm_interrupts(adata->acp_base); + return 0; +} + +static const struct dev_pm_ops acp_pdm_pm_ops = { + .runtime_suspend = acp_pdm_runtime_suspend, + .runtime_resume = acp_pdm_runtime_resume, + .resume = acp_pdm_resume, +}; + static struct platform_driver acp_pdm_dma_driver = { .probe = acp_pdm_audio_probe, .remove = acp_pdm_audio_remove, .driver = { .name = "acp_rn_pdm_dma", + .pm = &acp_pdm_pm_ops, }, }; From c15f258e6791e62c57d340c961de89261e48dc0a Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:17:01 +0800 Subject: [PATCH 314/428] ASoC: amd: enable Renoir acp3x drivers build Renoir ACP3x drivers can be built by selecting necessary kernel config option. The patch enables build support of the same. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-12-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 6 ++++++ sound/soc/amd/Makefile | 1 + sound/soc/amd/renoir/Makefile | 6 ++++++ 3 files changed, 13 insertions(+) create mode 100644 sound/soc/amd/renoir/Makefile diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index bce4cee5cb54..5f57a47382b4 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -36,3 +36,9 @@ config SND_SOC_AMD_RV_RT5682_MACH depends on SND_SOC_AMD_ACP3x && I2C && CROS_EC help This option enables machine driver for RT5682 and MAX9835. + +config SND_SOC_AMD_RENOIR + tristate "AMD Audio Coprocessor - Renoir support" + depends on X86 && PCI + help + This option enables ACP support for Renoir platform diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile index e6f3d9b469f3..e6df2f72a2a1 100644 --- a/sound/soc/amd/Makefile +++ b/sound/soc/amd/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH) += snd-soc-acp-da7219mx98357-mac obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/ obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o +obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/ diff --git a/sound/soc/amd/renoir/Makefile b/sound/soc/amd/renoir/Makefile new file mode 100644 index 000000000000..43100515c7db --- /dev/null +++ b/sound/soc/amd/renoir/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Renoir platform Support +snd-rn-pci-acp3x-objs := rn-pci-acp3x.o +snd-acp3x-pdm-dma-objs := acp3x-pdm-dma.o +obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-rn-pci-acp3x.o +obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-acp3x-pdm-dma.o From b208c3bc33542ab5a689f9b7a5f6ffc1a3da2944 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:17:02 +0800 Subject: [PATCH 315/428] ASoC: amd: create platform devices for Renoir Create platform devices for generic dmic codec driver and machine driver. These platform devices required for creation of sound card. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-13-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/rn-pci-acp3x.c | 49 ++++++++++++++++++----------- sound/soc/amd/renoir/rn_acp3x.h | 1 + 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index 71bfae644372..502c3f794ba0 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -21,7 +21,7 @@ MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating"); struct acp_dev_data { void __iomem *acp_base; struct resource *res; - struct platform_device *pdev; + struct platform_device *pdev[ACP_DEVS]; }; static int rn_acp_power_on(void __iomem *acp_base) @@ -156,9 +156,9 @@ static int snd_rn_acp_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { struct acp_dev_data *adata; - struct platform_device_info pdevinfo; + struct platform_device_info pdevinfo[ACP_DEVS]; unsigned int irqflags; - int ret; + int ret, index; u32 addr; if (pci_enable_device(pci)) { @@ -219,20 +219,29 @@ static int snd_rn_acp_probe(struct pci_dev *pci, adata->res[1].end = pci->irq; memset(&pdevinfo, 0, sizeof(pdevinfo)); - pdevinfo.name = "acp_rn_pdm_dma"; - pdevinfo.id = 0; - pdevinfo.parent = &pci->dev; - pdevinfo.num_res = 2; - pdevinfo.res = adata->res; - pdevinfo.data = &irqflags; - pdevinfo.size_data = sizeof(irqflags); + pdevinfo[0].name = "acp_rn_pdm_dma"; + pdevinfo[0].id = 0; + pdevinfo[0].parent = &pci->dev; + pdevinfo[0].num_res = 2; + pdevinfo[0].res = adata->res; + pdevinfo[0].data = &irqflags; + pdevinfo[0].size_data = sizeof(irqflags); - adata->pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(adata->pdev)) { - dev_err(&pci->dev, "cannot register %s device\n", - pdevinfo.name); - ret = PTR_ERR(adata->pdev); - goto unregister_devs; + pdevinfo[1].name = "dmic-codec"; + pdevinfo[1].id = 0; + pdevinfo[1].parent = &pci->dev; + pdevinfo[2].name = "acp_pdm_mach"; + pdevinfo[2].id = 0; + pdevinfo[2].parent = &pci->dev; + for (index = 0; index < ACP_DEVS; index++) { + adata->pdev[index] = + platform_device_register_full(&pdevinfo[index]); + if (IS_ERR(adata->pdev[index])) { + dev_err(&pci->dev, "cannot register %s device\n", + pdevinfo[index].name); + ret = PTR_ERR(adata->pdev[index]); + goto unregister_devs; + } } pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); pm_runtime_use_autosuspend(&pci->dev); @@ -241,7 +250,8 @@ static int snd_rn_acp_probe(struct pci_dev *pci, return 0; unregister_devs: - platform_device_unregister(adata->pdev); + for (index = 0; index < ACP_DEVS; index++) + platform_device_unregister(adata->pdev[index]); de_init: if (rn_acp_deinit(adata->acp_base)) dev_err(&pci->dev, "ACP de-init failed\n"); @@ -294,10 +304,11 @@ static const struct dev_pm_ops rn_acp_pm = { static void snd_rn_acp_remove(struct pci_dev *pci) { struct acp_dev_data *adata; - int ret; + int ret, index; adata = pci_get_drvdata(pci); - platform_device_unregister(adata->pdev); + for (index = 0; index < ACP_DEVS; index++) + platform_device_unregister(adata->pdev[index]); ret = rn_acp_deinit(adata->acp_base); if (ret) dev_err(&pci->dev, "ACP de-init failed\n"); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index 6e1888167fb3..75228e306e0b 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -7,6 +7,7 @@ #include "rn_chip_offset_byte.h" +#define ACP_DEVS 3 #define ACP_PHY_BASE_ADDRESS 0x1240000 #define ACP_REG_START 0x1240000 #define ACP_REG_END 0x1250200 From 7ca448a518cf40e161051f0fb69f550a1a636324 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:17:03 +0800 Subject: [PATCH 316/428] ASoC: amd: RN machine driver using dmic This patch adds Renoir Machine driver for dmic support. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-14-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-rn.c | 77 +++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 sound/soc/amd/renoir/acp3x-rn.c diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c new file mode 100644 index 000000000000..306134b89a82 --- /dev/null +++ b/sound/soc/amd/renoir/acp3x-rn.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Machine driver for AMD Renoir platform using DMIC +// +//Copyright 2020 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include + +#include "rn_acp3x.h" + +#define DRV_NAME "acp_pdm_mach" + +SND_SOC_DAILINK_DEF(acp_pdm, + DAILINK_COMP_ARRAY(COMP_CPU("acp_rn_pdm_dma.0"))); + +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec.0", + "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_rn_pdm_dma.0"))); + +static struct snd_soc_dai_link acp_dai_pdm[] = { + { + .name = "acp3x-dmic-capture", + .stream_name = "DMIC capture", + .capture_only = 1, + SND_SOC_DAILINK_REG(acp_pdm, dmic_codec, platform), + }, +}; + +static struct snd_soc_card acp_card = { + .name = "acp", + .owner = THIS_MODULE, + .dai_link = acp_dai_pdm, + .num_links = 1, +}; + +static int acp_probe(struct platform_device *pdev) +{ + int ret; + struct acp_pdm *machine = NULL; + struct snd_soc_card *card; + + card = &acp_card; + acp_card.dev = &pdev->dev; + + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, machine); + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + dev_err(&pdev->dev, + "snd_soc_register_card(%s) failed: %d\n", + acp_card.name, ret); + return ret; + } + return 0; +} + +static struct platform_driver acp_mach_driver = { + .driver = { + .name = "acp_pdm_mach", + .pm = &snd_soc_pm_ops, + }, + .probe = acp_probe, +}; + +module_platform_driver(acp_mach_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); From 1d3776669323e71b00c99a178317fc46edbd09bb Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 01:17:04 +0800 Subject: [PATCH 317/428] ASoC: amd: enable build for RN machine driver This patch enables build for RN machine driver. Signed-off-by: Vijendar Mukunda Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200518171704.24999-15-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 7 +++++++ sound/soc/amd/renoir/Makefile | 1 + 2 files changed, 8 insertions(+) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 5f57a47382b4..77ffdb41bee5 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -42,3 +42,10 @@ config SND_SOC_AMD_RENOIR depends on X86 && PCI help This option enables ACP support for Renoir platform + +config SND_SOC_AMD_RENOIR_MACH + tristate "AMD Renoir support for DMIC" + select SND_SOC_DMIC + depends on SND_SOC_AMD_RENOIR + help + This option enables machine driver for DMIC diff --git a/sound/soc/amd/renoir/Makefile b/sound/soc/amd/renoir/Makefile index 43100515c7db..e4371932a55a 100644 --- a/sound/soc/amd/renoir/Makefile +++ b/sound/soc/amd/renoir/Makefile @@ -4,3 +4,4 @@ snd-rn-pci-acp3x-objs := rn-pci-acp3x.o snd-acp3x-pdm-dma-objs := acp3x-pdm-dma.o obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-rn-pci-acp3x.o obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-acp3x-pdm-dma.o +obj-$(CONFIG_SND_SOC_AMD_RENOIR_MACH) += acp3x-rn.o From f8953043e6e24f9425249464605a541d00950709 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Tue, 12 May 2020 18:22:59 +0800 Subject: [PATCH 318/428] ASoC: fsl_asrc: Set ASR76K and ASR56K based on processing clock The processing clock is different for platforms, so it is better to set ASR76K and ASR56K based on processing clock, rather than hard coding the value for them. Signed-off-by: Shengjiu Wang Signed-off-by: Mihai Serban Link: https://lore.kernel.org/r/1589278979-31008-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 432936039de4..7e2d598ffb81 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -858,6 +858,8 @@ static const struct regmap_config fsl_asrc_regmap_config = { */ static int fsl_asrc_init(struct fsl_asrc *asrc) { + unsigned long ipg_rate; + /* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */ regmap_write(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEN); @@ -875,11 +877,14 @@ static int fsl_asrc_init(struct fsl_asrc *asrc) regmap_update_bits(asrc->regmap, REG_ASRTFR1, ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc)); - /* Set the processing clock for 76KHz to 133M */ - regmap_write(asrc->regmap, REG_ASR76K, 0x06D6); - - /* Set the processing clock for 56KHz to 133M */ - return regmap_write(asrc->regmap, REG_ASR56K, 0x0947); + /* + * Set the period of the 76KHz and 56KHz sampling clocks based on + * the ASRC processing clock. + * On iMX6, ipg_clk = 133MHz, REG_ASR76K = 0x06D6, REG_ASR56K = 0x0947 + */ + ipg_rate = clk_get_rate(asrc->ipg_clk); + regmap_write(asrc->regmap, REG_ASR76K, ipg_rate / 76000); + return regmap_write(asrc->regmap, REG_ASR56K, ipg_rate / 56000); } /** From 1a90a659865299c04ba97b299ab02238dc392d5f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 18 May 2020 15:54:47 -0300 Subject: [PATCH 319/428] ASoC: fsl_micfil: Remove unneeded ifdef's There is no need to use ifdef's around the power managament related functions, as they are already using the __maybe_unused notation. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20200518185448.6116-1-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 59cf95fa2b2d..8c8dd42b1175 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -752,7 +752,6 @@ static int fsl_micfil_probe(struct platform_device *pdev) return ret; } -#ifdef CONFIG_PM static int __maybe_unused fsl_micfil_runtime_suspend(struct device *dev) { struct fsl_micfil *micfil = dev_get_drvdata(dev); @@ -779,9 +778,7 @@ static int __maybe_unused fsl_micfil_runtime_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM*/ -#ifdef CONFIG_PM_SLEEP static int __maybe_unused fsl_micfil_suspend(struct device *dev) { pm_runtime_force_suspend(dev); @@ -795,7 +792,6 @@ static int __maybe_unused fsl_micfil_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops fsl_micfil_pm_ops = { SET_RUNTIME_PM_OPS(fsl_micfil_runtime_suspend, From a62ed9606aaebef00ca32da01e552bc0162c29b5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 18 May 2020 15:54:48 -0300 Subject: [PATCH 320/428] ASoC: fsl_micfil: Do not pass irq numbers in comments The IRQ numbers may change depending on the SoC, so do not pass the IRQ numbers in the comments. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20200518185448.6116-2-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 8c8dd42b1175..efc5daf53bba 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -708,7 +708,7 @@ static int fsl_micfil_probe(struct platform_device *pdev) if (of_property_read_bool(np, "fsl,shared-interrupt")) irqflag = IRQF_SHARED; - /* Digital Microphone interface interrupt - IRQ 109 */ + /* Digital Microphone interface interrupt */ ret = devm_request_irq(&pdev->dev, micfil->irq[0], micfil_isr, irqflag, micfil->name, micfil); @@ -718,7 +718,7 @@ static int fsl_micfil_probe(struct platform_device *pdev) return ret; } - /* Digital Microphone interface error interrupt - IRQ 110 */ + /* Digital Microphone interface error interrupt */ ret = devm_request_irq(&pdev->dev, micfil->irq[1], micfil_err_isr, irqflag, micfil->name, micfil); From fdae433e5129c4ca87716de08fdcc0034d5aabc8 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 22:34:20 +0800 Subject: [PATCH 321/428] ASoC: amd: fix kernel warning Removed unused variable from code to fix the kernel warning. Reported-by: kbuild test robot Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20200519143422.18255-1-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 942010021319..b33c7aec7481 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -150,12 +150,11 @@ static int start_pdm_dma(void __iomem *acp_base) static int stop_pdm_dma(void __iomem *acp_base) { - u32 pdm_enable, pdm_dma_enable, pdm_fifo_flush; + u32 pdm_enable, pdm_dma_enable; int timeout; pdm_enable = 0x00; pdm_dma_enable = 0x00; - pdm_fifo_flush = 0x00; pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE); pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); From 19cc20bd644f7baf279671c0647ef79c36f259a3 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 22:34:21 +0800 Subject: [PATCH 322/428] ASoC: amd: refactoring dai_hw_params() callback Removed api config_pdm_stream_params(). Modified switch case for channel check. Default case should return -EINVAL. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20200519143422.18255-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index b33c7aec7481..623dfd3ea705 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -72,14 +72,6 @@ static void init_pdm_ring_buffer(u32 physical_addr, rn_writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL); } -static void config_pdm_stream_params(unsigned int ch_mask, - void __iomem *acp_base) -{ - rn_writel(ch_mask, acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); - rn_writel(PDM_DECIMATION_FACTOR, acp_base + - ACP_WOV_PDM_DECIMATION_FACTOR); -} - static void enable_pdm_clock(void __iomem *acp_base) { u32 pdm_clk_enable, pdm_ctrl; @@ -332,11 +324,14 @@ static int acp_pdm_dai_hw_params(struct snd_pcm_substream *substream, rtd = substream->runtime->private_data; switch (params_channels(params)) { case TWO_CH: - default: ch_mask = 0x00; break; + default: + return -EINVAL; } - config_pdm_stream_params(ch_mask, rtd->acp_base); + rn_writel(ch_mask, rtd->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); + rn_writel(PDM_DECIMATION_FACTOR, rtd->acp_base + + ACP_WOV_PDM_DECIMATION_FACTOR); return 0; } From ce5955866d971864a6cd8d012411ec96b048a696 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 19 May 2020 22:34:22 +0800 Subject: [PATCH 323/428] ASoC: amd: return error when acp de-init fails Return error when acp de-init fails during suspend. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20200519143422.18255-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/rn-pci-acp3x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index 502c3f794ba0..859ed67b93cf 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -277,7 +277,7 @@ static int snd_rn_acp_suspend(struct device *dev) else dev_dbg(dev, "ACP de-initialized\n"); - return 0; + return ret; } static int snd_rn_acp_resume(struct device *dev) From a97e384ba78fd8bf7ba8c32718424d8a7536416e Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:34 +0200 Subject: [PATCH 324/428] ASoC: mmp-sspa: Add Device Tree support This makes it possible to select CONFIG_SND_MMP_SOC_SSPA directly, as opposed to via CONFIG_SND_MMP_SOC, and for the driver to bind to a device tree node. That makes the driver useful on Device Tree based systems, with audio-graph-card or simple-card. The aforementioned card drivers control the master clock themselves and don't call the set_dai_sysclk() or set_dai_pll(), thus the respective handlers don't serve any purpose anymore. Instead, they return early and the hw_params() handler sets the appropriate bitclk itself. The register range is split into two -- for the RX block and for the TX block. On a MMP2 there are two pairs of them; the first one has the clock controller in the middle, while the second just has a hole: 0xd42a0c00 - 0xd42a0c30 RX1 0xd42a0c30 - 0xd42a0c40 Clocks 0xd42a0c80 - 0xd42a0cb0 TX1 0xd42a0d00 - 0xd42a0d30 RX2 0xd42a0d80 - 0xd42a0cb0 TX2 For this reason, mmp_sspa_write_reg() and mmp_sspa_read_reg() are replaced with direct calls to I/O routines. Tested on a MMP2-based OLPC XO-1.75 laptop with rt5631 coded, mmp_tdma DMA engine and MMP2 clock controller glued together with audio-graph-card. Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200511210134.1224532-12-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 20 +++--- sound/soc/pxa/mmp-sspa.c | 139 ++++++++++++++++++++++++++------------- sound/soc/pxa/mmp-sspa.h | 28 +++----- 3 files changed, 113 insertions(+), 74 deletions(-) diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index d4c0f580a565..7ad2fd7e653b 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -9,14 +9,8 @@ config SND_PXA2XX_SOC to select the audio interfaces to support below. config SND_MMP_SOC - bool "Soc Audio for Marvell MMP chips" - depends on ARCH_MMP + bool select MMP_SRAM - select SND_SOC_GENERIC_DMAENGINE_PCM - select SND_ARM - help - Say Y if you want to add support for codecs attached to - the MMP SSPA interface. config SND_PXA2XX_AC97 tristate @@ -39,7 +33,13 @@ config SND_PXA_SOC_SSP select SND_PXA2XX_LIB config SND_MMP_SOC_SSPA - tristate + tristate "SoC Audio via MMP SSPA ports" + depends on ARCH_MMP + select SND_SOC_GENERIC_DMAENGINE_PCM + select SND_ARM + help + Say Y if you want to add support for codecs attached to + the MMP SSPA interface. config SND_PXA2XX_SOC_CORGI tristate "SoC Audio support for Sharp Zaurus SL-C7x0" @@ -232,8 +232,8 @@ config SND_PXA2XX_SOC_IMOTE2 config SND_MMP_SOC_BROWNSTONE tristate "SoC Audio support for Marvell Brownstone" - depends on SND_MMP_SOC && MACH_BROWNSTONE && I2C - select SND_MMP_SOC_SSPA + depends on SND_MMP_SOC_SSPA && MACH_BROWNSTONE && I2C + select SND_MMP_SOC select MFD_WM8994 select SND_SOC_WM8994 help diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 86277471974a..b0accd49c89d 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -28,27 +28,20 @@ * SSPA audio private data */ struct sspa_priv { - void __iomem *mmio_base; + void __iomem *tx_base; + void __iomem *rx_base; + struct snd_dmaengine_dai_dma_data playback_dma_data; struct snd_dmaengine_dai_dma_data capture_dma_data; struct clk *clk; struct clk *audio_clk; struct clk *sysclk; + int running_cnt; u32 sp; u32 ctrl; }; -static void mmp_sspa_write_reg(struct sspa_priv *sspa, u32 reg, u32 val) -{ - __raw_writel(val, sspa->mmio_base + reg); -} - -static u32 mmp_sspa_read_reg(struct sspa_priv *sspa, u32 reg) -{ - return __raw_readl(sspa->mmio_base + reg); -} - static void mmp_sspa_tx_enable(struct sspa_priv *sspa) { unsigned int sspa_sp = sspa->sp; @@ -56,7 +49,7 @@ static void mmp_sspa_tx_enable(struct sspa_priv *sspa) sspa_sp &= ~SSPA_SP_MSL; sspa_sp |= SSPA_SP_S_EN; sspa_sp |= SSPA_SP_WEN; - mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); + __raw_writel(sspa_sp, sspa->tx_base + SSPA_SP); } static void mmp_sspa_tx_disable(struct sspa_priv *sspa) @@ -66,7 +59,7 @@ static void mmp_sspa_tx_disable(struct sspa_priv *sspa) sspa_sp &= ~SSPA_SP_MSL; sspa_sp &= ~SSPA_SP_S_EN; sspa_sp |= SSPA_SP_WEN; - mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); + __raw_writel(sspa_sp, sspa->tx_base + SSPA_SP); } static void mmp_sspa_rx_enable(struct sspa_priv *sspa) @@ -75,7 +68,7 @@ static void mmp_sspa_rx_enable(struct sspa_priv *sspa) sspa_sp |= SSPA_SP_S_EN; sspa_sp |= SSPA_SP_WEN; - mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); + __raw_writel(sspa_sp, sspa->rx_base + SSPA_SP); } static void mmp_sspa_rx_disable(struct sspa_priv *sspa) @@ -84,7 +77,7 @@ static void mmp_sspa_rx_disable(struct sspa_priv *sspa) sspa_sp &= ~SSPA_SP_S_EN; sspa_sp |= SSPA_SP_WEN; - mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); + __raw_writel(sspa_sp, sspa->rx_base + SSPA_SP); } static int mmp_sspa_startup(struct snd_pcm_substream *substream, @@ -105,7 +98,6 @@ static void mmp_sspa_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(sspa->clk); clk_disable_unprepare(sspa->sysclk); - } /* @@ -115,8 +107,12 @@ static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); + struct device *dev = cpu_dai->component->dev; int ret = 0; + if (dev->of_node) + return -ENOTSUPP; + switch (clk_id) { case MMP_SSPA_CLK_AUDIO: ret = clk_set_rate(sspa->audio_clk, freq); @@ -139,8 +135,12 @@ static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, unsigned int freq_out) { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); + struct device *dev = cpu_dai->component->dev; int ret = 0; + if (dev->of_node) + return -ENOTSUPP; + switch (pll_id) { case MMP_SYSCLK: ret = clk_set_rate(sspa->sysclk, freq_out); @@ -213,6 +213,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); + struct device *dev = dai->component->dev; u32 sspa_ctrl = sspa->ctrl; int bits; int bitval; @@ -238,7 +239,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - if (params_channels(params) == 2) + if (dev->of_node || params_channels(params) == 2) sspa_ctrl |= SSPA_CTL_XPH; sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK; @@ -256,12 +257,17 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, sspa->sp &= ~SSPA_TXSP_FPER_MASK; sspa->sp |= SSPA_TXSP_FPER(bits * 2 - 1); + if (dev->of_node) { + clk_set_rate(sspa->clk, params_rate(params) * + params_channels(params) * bits); + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); - mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1); + __raw_writel(sspa_ctrl, sspa->tx_base + SSPA_CTL); + __raw_writel(0x1, sspa->tx_base + SSPA_FIFO_UL); } else { - mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl); - mmp_sspa_write_reg(sspa, SSPA_RXFIFO_UL, 0x0); + __raw_writel(sspa_ctrl, sspa->rx_base + SSPA_CTL); + __raw_writel(0x0, sspa->rx_base + SSPA_FIFO_UL); } return 0; @@ -410,19 +416,19 @@ static int mmp_sspa_open(struct snd_soc_component *component, pm_runtime_get_sync(component->dev); /* we can only change the settings if the port is not in use */ - if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) || - (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) { + if ((__raw_readl(sspa->tx_base + SSPA_SP) & SSPA_SP_S_EN) || + (__raw_readl(sspa->rx_base + SSPA_SP) & SSPA_SP_S_EN)) { dev_err(component->dev, "can't change hardware dai format: stream is in use\n"); return -EBUSY; } - mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa->sp); - mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa->sp); + __raw_writel(sspa->sp, sspa->tx_base + SSPA_SP); + __raw_writel(sspa->sp, sspa->rx_base + SSPA_SP); sspa->sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH); - mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa->sp); - mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa->sp); + __raw_writel(sspa->sp, sspa->tx_base + SSPA_SP); + __raw_writel(sspa->sp, sspa->rx_base + SSPA_SP); /* * FIXME: hw issue, for the tx serial port, @@ -431,10 +437,10 @@ static int mmp_sspa_open(struct snd_soc_component *component, * The master/slave mode has been set in the * rx port. */ - mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa->sp & ~SSPA_SP_MSL); + __raw_writel(sspa->sp & ~SSPA_SP_MSL, sspa->tx_base + SSPA_SP); - mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa->ctrl); - mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa->ctrl); + __raw_writel(sspa->ctrl, sspa->tx_base + SSPA_CTL); + __raw_writel(sspa->ctrl, sspa->rx_base + SSPA_CTL); return 0; } @@ -462,22 +468,51 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) if (!sspa) return -ENOMEM; - sspa->mmio_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(sspa->mmio_base)) - return PTR_ERR(sspa->mmio_base); + if (pdev->dev.of_node) { + sspa->rx_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(sspa->rx_base)) + return PTR_ERR(sspa->rx_base); - sspa->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(sspa->clk)) - return PTR_ERR(sspa->clk); + sspa->tx_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(sspa->tx_base)) + return PTR_ERR(sspa->tx_base); - sspa->audio_clk = clk_get(NULL, "mmp-audio"); - if (IS_ERR(sspa->audio_clk)) - return PTR_ERR(sspa->audio_clk); + sspa->clk = devm_clk_get(&pdev->dev, "bitclk"); + if (IS_ERR(sspa->clk)) + return PTR_ERR(sspa->clk); - sspa->sysclk = clk_get(NULL, "mmp-sysclk"); - if (IS_ERR(sspa->sysclk)) { - clk_put(sspa->audio_clk); - return PTR_ERR(sspa->sysclk); + sspa->audio_clk = devm_clk_get(&pdev->dev, "audio"); + if (IS_ERR(sspa->audio_clk)) + return PTR_ERR(sspa->audio_clk); + } else { + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (res == NULL) + return -ENODEV; + + sspa->rx_base = devm_ioremap(&pdev->dev, res->start, 0x30); + if (IS_ERR(sspa->rx_base)) + return PTR_ERR(sspa->rx_base); + + sspa->tx_base = devm_ioremap(&pdev->dev, + res->start + 0x80, 0x30); + if (IS_ERR(sspa->tx_base)) + return PTR_ERR(sspa->tx_base); + + sspa->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(sspa->clk)) + return PTR_ERR(sspa->clk); + + sspa->audio_clk = clk_get(NULL, "mmp-audio"); + if (IS_ERR(sspa->audio_clk)) + return PTR_ERR(sspa->audio_clk); + + sspa->sysclk = clk_get(NULL, "mmp-sysclk"); + if (IS_ERR(sspa->sysclk)) { + clk_put(sspa->audio_clk); + return PTR_ERR(sspa->sysclk); + } } pm_runtime_enable(&pdev->dev); clk_prepare_enable(sspa->audio_clk); @@ -486,8 +521,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) sspa->playback_dma_data.maxburst = 4; sspa->capture_dma_data.maxburst = 4; /* You know, these addresses are actually ignored. */ - sspa->playback_dma_data.addr = SSPA_TXD; - sspa->capture_dma_data.addr = SSPA_RXD; + sspa->capture_dma_data.addr = SSPA_D; + sspa->playback_dma_data.addr = 0x80 + SSPA_D; if (pdev->dev.of_node) { int ret; @@ -508,14 +543,28 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev) clk_disable_unprepare(sspa->audio_clk); pm_runtime_disable(&pdev->dev); + + if (pdev->dev.of_node) + return 0; + clk_put(sspa->audio_clk); clk_put(sspa->sysclk); return 0; } +#ifdef CONFIG_OF +static const struct of_device_id mmp_sspa_of_match[] = { + { .compatible = "marvell,mmp-sspa" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, mmp_sspa_of_match); +#endif + static struct platform_driver asoc_mmp_sspa_driver = { .driver = { .name = "mmp-sspa-dai", + .of_match_table = of_match_ptr(mmp_sspa_of_match), }, .probe = asoc_mmp_sspa_probe, .remove = asoc_mmp_sspa_remove, diff --git a/sound/soc/pxa/mmp-sspa.h b/sound/soc/pxa/mmp-sspa.h index 328969b57ad1..938ef2f667e3 100644 --- a/sound/soc/pxa/mmp-sspa.h +++ b/sound/soc/pxa/mmp-sspa.h @@ -10,25 +10,15 @@ /* * SSPA Registers */ -#define SSPA_RXD (0x00) -#define SSPA_RXID (0x04) -#define SSPA_RXCTL (0x08) -#define SSPA_RXSP (0x0c) -#define SSPA_RXFIFO_UL (0x10) -#define SSPA_RXINT_MASK (0x14) -#define SSPA_RXC (0x18) -#define SSPA_RXFIFO_NOFS (0x1c) -#define SSPA_RXFIFO_SIZE (0x20) - -#define SSPA_TXD (0x80) -#define SSPA_TXID (0x84) -#define SSPA_TXCTL (0x88) -#define SSPA_TXSP (0x8c) -#define SSPA_TXFIFO_LL (0x90) -#define SSPA_TXINT_MASK (0x94) -#define SSPA_TXC (0x98) -#define SSPA_TXFIFO_NOFS (0x9c) -#define SSPA_TXFIFO_SIZE (0xa0) +#define SSPA_D (0x00) +#define SSPA_ID (0x04) +#define SSPA_CTL (0x08) +#define SSPA_SP (0x0c) +#define SSPA_FIFO_UL (0x10) +#define SSPA_INT_MASK (0x14) +#define SSPA_C (0x18) +#define SSPA_FIFO_NOFS (0x1c) +#define SSPA_FIFO_SIZE (0x20) /* SSPA Control Register */ #define SSPA_CTL_XPH (1 << 31) /* Read Phase */ From d81bb8726c247c3e7719d21bf213c5400de29e03 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 11 May 2020 23:01:33 +0200 Subject: [PATCH 325/428] ASoC: Add Marvell MMP SSPA binding Add binding documentation for the audio serial port interface (I2S) on Marvell MMP SoCs. Signed-off-by: Lubomir Rintel Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200511210134.1224532-11-lkundrak@v3.sk Signed-off-by: Mark Brown --- .../bindings/sound/marvell,mmp-sspa.yaml | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml diff --git a/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml b/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml new file mode 100644 index 000000000000..6d20a24a2ae9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/marvell,mmp-sspa.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvel SSPA Digital Audio Interface Bindings + +maintainers: + - Lubomir Rintel + +properties: + $nodename: + pattern: "^audio-controller(@.*)?$" + + compatible: + const: marvell,mmp-sspa + + reg: + items: + - description: RX block + - description: TX block + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Clock for the Audio block + - description: I2S bit clock + + clock-names: + items: + - const: audio + - const: bitclk + + power-domains: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + dmas: + items: + - description: TX DMA Channel + - description: RX DMA Channel + + dma-names: + items: + - const: tx + - const: rx + + port: + type: object + + properties: + endpoint: + type: object + + properties: + remote-endpoint: true + + frame-master: + type: boolean + description: SoC generates the frame clock + + bitclock-master: + type: boolean + description: SoC generates the bit clock + + dai-format: + $ref: /schemas/types.yaml#/definitions/string + description: The digital audio format + const: i2s + + required: + - remote-endpoint + + required: + - endpoint + + additionalProperties: false + +required: + - "#sound-dai-cells" + - compatible + - reg + - interrupts + - clocks + - clock-names + - dmas + - dma-names + - port + +additionalProperties: false + +examples: + - | + #include + + audio-controller@d42a0c00 { + compatible = "marvell,mmp-sspa"; + reg = <0xd42a0c00 0x30>, + <0xd42a0c80 0x30>; + interrupts = <2>; + clock-names = "audio", "bitclk"; + clocks = <&soc_clocks 127>, + <&audio_clk 1>; + #sound-dai-cells = <0>; + dmas = <&adma0 0>, <&adma0 1>; + dma-names = "tx", "rx"; + port { + endpoint { + remote-endpoint = <&rt5631_0>; + frame-master; + bitclock-master; + dai-format = "i2s"; + }; + }; + }; + +... From 53a58bf96bcdd47c670a957920f3a1bcf7215b39 Mon Sep 17 00:00:00 2001 From: Pavel Dobias Date: Wed, 20 May 2020 09:18:59 +0200 Subject: [PATCH 326/428] ASoC: max9867: fix ADC level control Fix swapped channels in ADC level control. Signed-off-by: Pavel Dobias Link: https://lore.kernel.org/r/20200520071904.15801-1-dobias@2n.cz Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 2e4aa23b5a60..6d49a1cc98c6 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -58,7 +58,7 @@ static const struct snd_kcontrol_new max9867_snd_controls[] = { max9867_dac_tlv), SOC_SINGLE_TLV("Digital Boost Playback Volume", MAX9867_DACLEVEL, 4, 3, 0, max9867_dacboost_tlv), - SOC_DOUBLE_TLV("Digital Capture Volume", MAX9867_ADCLEVEL, 0, 4, 15, 1, + SOC_DOUBLE_TLV("Digital Capture Volume", MAX9867_ADCLEVEL, 4, 0, 15, 1, max9867_adc_tlv), SOC_ENUM("Speaker Mode", max9867_spkmode), SOC_SINGLE("Volume Smoothing Switch", MAX9867_MODECONFIG, 6, 1, 0), From 6ea460d52299f7febd408f2710d7c43ce505bc2c Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 20 May 2020 10:35:16 +0200 Subject: [PATCH 327/428] ASoC: mmp-sspa: Fix the error handling in probe() If we fail after pm_runtime_enable(), we fail to undo it. Same with clk_prepare_enable(). Let's order them after all things that can fail. Fixes: 7d98cc648253 ("ASoC: mmp-sspa: Add support for the runtime power management") Signed-off-by: Lubomir Rintel Link: https://lore.kernel.org/r/20200520083516.2120802-1-lkundrak@v3.sk Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index b0accd49c89d..3e37ab625f8d 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -462,6 +462,7 @@ static const struct snd_soc_component_driver mmp_sspa_component = { static int asoc_mmp_sspa_probe(struct platform_device *pdev) { struct sspa_priv *sspa; + int ret; sspa = devm_kzalloc(&pdev->dev, sizeof(struct sspa_priv), GFP_KERNEL); @@ -514,8 +515,6 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) return PTR_ERR(sspa->sysclk); } } - pm_runtime_enable(&pdev->dev); - clk_prepare_enable(sspa->audio_clk); platform_set_drvdata(pdev, sspa); sspa->playback_dma_data.maxburst = 4; @@ -525,16 +524,21 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) sspa->playback_dma_data.addr = 0x80 + SSPA_D; if (pdev->dev.of_node) { - int ret; - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, &mmp_pcm_config, 0); if (ret) return ret; } - return devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component, - &mmp_sspa_dai, 1); + ret = devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component, + &mmp_sspa_dai, 1); + if (ret) + return ret; + + pm_runtime_enable(&pdev->dev); + clk_prepare_enable(sspa->audio_clk); + + return 0; } static int asoc_mmp_sspa_remove(struct platform_device *pdev) From d0de8c69f90196fb872f1739756bb0348144d18c Mon Sep 17 00:00:00 2001 From: Pavel Dobias Date: Wed, 20 May 2020 09:19:00 +0200 Subject: [PATCH 328/428] ASoC: max9867: don't use regmap defaults MAX9867 codec doesn't have reset pin, so the registers don't have default values in the case of reboot without powering off. Remove the reg_defaults struct and let the regmap read initial state of the registers at startup instead of taking them from reg_defaults struct. Signed-off-by: Pavel Dobias Link: https://lore.kernel.org/r/20200520071904.15801-2-dobias@2n.cz Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 8600c5439e1e..521aaa193607 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -463,35 +463,10 @@ static bool max9867_volatile_register(struct device *dev, unsigned int reg) } } -static const struct reg_default max9867_reg[] = { - { 0x04, 0x00 }, - { 0x05, 0x00 }, - { 0x06, 0x00 }, - { 0x07, 0x00 }, - { 0x08, 0x00 }, - { 0x09, 0x00 }, - { 0x0A, 0x00 }, - { 0x0B, 0x00 }, - { 0x0C, 0x00 }, - { 0x0D, 0x00 }, - { 0x0E, 0x40 }, - { 0x0F, 0x40 }, - { 0x10, 0x00 }, - { 0x11, 0x00 }, - { 0x12, 0x00 }, - { 0x13, 0x00 }, - { 0x14, 0x00 }, - { 0x15, 0x00 }, - { 0x16, 0x00 }, - { 0x17, 0x00 }, -}; - static const struct regmap_config max9867_regmap = { .reg_bits = 8, .val_bits = 8, .max_register = MAX9867_REVISION, - .reg_defaults = max9867_reg, - .num_reg_defaults = ARRAY_SIZE(max9867_reg), .volatile_reg = max9867_volatile_register, .cache_type = REGCACHE_RBTREE, }; From af53d5738cb0fd61da0bc3f5a884df7af237d20d Mon Sep 17 00:00:00 2001 From: Pavel Dobias Date: Wed, 20 May 2020 09:19:01 +0200 Subject: [PATCH 329/428] ASoC: max9867: add filter controls Adding missing codec controls - ADC/DAC IIR filter selection. Signed-off-by: Pavel Dobias Link: https://lore.kernel.org/r/20200520071904.15801-3-dobias@2n.cz Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 521aaa193607..22e06a795042 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -23,8 +23,21 @@ static const char *const max9867_spmode[] = { }; static const char *const max9867_filter_text[] = {"IIR", "FIR"}; +static const char *const max9867_adc_dac_filter_text[] = { + "Disabled", + "Elliptical/16/256", + "Butterworth/16/500", + "Elliptical/8/256", + "Butterworth/8/500", + "Butterworth/8-24" +}; + static SOC_ENUM_SINGLE_DECL(max9867_filter, MAX9867_CODECFLTR, 7, max9867_filter_text); +static SOC_ENUM_SINGLE_DECL(max9867_dac_filter, MAX9867_CODECFLTR, 0, + max9867_adc_dac_filter_text); +static SOC_ENUM_SINGLE_DECL(max9867_adc_filter, MAX9867_CODECFLTR, 4, + max9867_adc_dac_filter_text); static SOC_ENUM_SINGLE_DECL(max9867_spkmode, MAX9867_MODECONFIG, 0, max9867_spmode); static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(max9867_master_tlv, @@ -64,6 +77,8 @@ static const struct snd_kcontrol_new max9867_snd_controls[] = { SOC_SINGLE("Volume Smoothing Switch", MAX9867_MODECONFIG, 6, 1, 0), SOC_SINGLE("Line ZC Switch", MAX9867_MODECONFIG, 5, 1, 0), SOC_ENUM("DSP Filter", max9867_filter), + SOC_ENUM("ADC Filter", max9867_adc_filter), + SOC_ENUM("DAC Filter", max9867_dac_filter), }; /* Input mixer */ From 80b9fa4dead406f9a0aef5b364eb237872986c2c Mon Sep 17 00:00:00 2001 From: Pavel Dobias Date: Wed, 20 May 2020 09:19:03 +0200 Subject: [PATCH 330/428] ASoC: max9867: add mono playback switch Add Mono Playback switch to codec controls which enables codec's capability of mixing left and right channel at the DAC output. Signed-off-by: Pavel Dobias Link: https://lore.kernel.org/r/20200520071904.15801-5-dobias@2n.cz Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 22e06a795042..f100070a59ca 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -79,6 +79,7 @@ static const struct snd_kcontrol_new max9867_snd_controls[] = { SOC_ENUM("DSP Filter", max9867_filter), SOC_ENUM("ADC Filter", max9867_adc_filter), SOC_ENUM("DAC Filter", max9867_dac_filter), + SOC_SINGLE("Mono Playback Switch", MAX9867_IFC1B, 3, 1, 0), }; /* Input mixer */ @@ -361,7 +362,8 @@ static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai, } regmap_write(max9867->regmap, MAX9867_IFC1A, iface1A); - regmap_write(max9867->regmap, MAX9867_IFC1B, iface1B); + regmap_update_bits(max9867->regmap, MAX9867_IFC1B, + MAX9867_IFC1B_BCLK_MASK, iface1B); return 0; } From 168aac9de09551bb0ac9bd3b7a311cd681894fc3 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 21 May 2020 20:51:39 +0200 Subject: [PATCH 331/428] ASoC: pxa: remove Compulab pxa2xx boards As these boards have been removed from the pxa tree, amend accordingly the sound subsystem. Signed-off-by: Robert Jarzmik Acked-by: Mike Rapoport Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20200521185140.27276-3-robert.jarzmik@free.fr Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 7ad2fd7e653b..0ac85eada75c 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -128,9 +128,8 @@ config SND_PXA2XX_SOC_E800 Toshiba e800 PDA config SND_PXA2XX_SOC_EM_X270 - tristate "SoC Audio support for CompuLab EM-x270, eXeda and CM-X300" - depends on SND_PXA2XX_SOC && (MACH_EM_X270 || MACH_EXEDA || \ - MACH_CM_X300) + tristate "SoC Audio support for CompuLab CM-X300" + depends on SND_PXA2XX_SOC && MACH_CM_X300 depends on AC97_BUS=n select REGMAP select AC97_BUS_NEW From 0a7c7b47e44f7062069f23a4d674c81eb7f4ad56 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:28 +0900 Subject: [PATCH 332/428] ALSA: firewire-motu: move spec data to v2 protocol file The most of members in spec data is used in each protocol file. It's better to capsulate the data to the file. This commit moves the data to the file for protocol version 2. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-2-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 57 +++++++++++++++++++++++ sound/firewire/motu/motu.c | 63 ++------------------------ sound/firewire/motu/motu.h | 3 ++ 3 files changed, 63 insertions(+), 60 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 619b6ae73f62..ed71c08e5942 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -300,3 +300,60 @@ const struct snd_motu_protocol snd_motu_protocol_v2 = { .switch_fetching_mode = v2_switch_fetching_mode, .cache_packet_formats = v2_cache_packet_formats, }; + +const struct snd_motu_spec snd_motu_spec_828mk2 = { + .name = "828mk2", + .protocol = &snd_motu_protocol_v2, + .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | + SND_MOTU_SPEC_TX_MICINST_CHUNK | + SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_RX_SEPARATED_MAIN | + SND_MOTU_SPEC_HAS_OPT_IFACE_A | + SND_MOTU_SPEC_RX_MIDI_2ND_Q | + SND_MOTU_SPEC_TX_MIDI_2ND_Q, + + .analog_in_ports = 8, + .analog_out_ports = 8, +}; + +const struct snd_motu_spec snd_motu_spec_traveler = { + .name = "Traveler", + .protocol = &snd_motu_protocol_v2, + .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | + SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | + SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_HAS_AESEBU_IFACE | + SND_MOTU_SPEC_HAS_OPT_IFACE_A | + SND_MOTU_SPEC_RX_MIDI_2ND_Q | + SND_MOTU_SPEC_TX_MIDI_2ND_Q, + + .analog_in_ports = 8, + .analog_out_ports = 8, +}; + +const struct snd_motu_spec snd_motu_spec_ultralite = { + .name = "UltraLite", + .protocol = &snd_motu_protocol_v2, + .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | + SND_MOTU_SPEC_TX_MICINST_CHUNK | // padding. + SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_RX_MIDI_2ND_Q | + SND_MOTU_SPEC_TX_MIDI_2ND_Q | + SND_MOTU_SPEC_RX_SEPARATED_MAIN, + .analog_in_ports = 8, + .analog_out_ports = 8, +}; + +const struct snd_motu_spec snd_motu_spec_8pre = { + .name = "8pre", + .protocol = &snd_motu_protocol_v2, + // In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for + // dummy 1/2. + .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | + SND_MOTU_SPEC_HAS_OPT_IFACE_A | + SND_MOTU_SPEC_HAS_OPT_IFACE_B | + SND_MOTU_SPEC_RX_MIDI_2ND_Q | + SND_MOTU_SPEC_TX_MIDI_2ND_Q, + .analog_in_ports = 8, + .analog_out_ports = 2, +}; diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index f2080d720aa9..b3533526f7e5 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c @@ -172,63 +172,6 @@ static void motu_bus_update(struct fw_unit *unit) snd_motu_transaction_reregister(motu); } -const struct snd_motu_spec snd_motu_spec_828mk2 = { - .name = "828mk2", - .protocol = &snd_motu_protocol_v2, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_RX_SEPARATED_MAIN | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | - SND_MOTU_SPEC_TX_MIDI_2ND_Q, - - .analog_in_ports = 8, - .analog_out_ports = 8, -}; - -static const struct snd_motu_spec motu_traveler = { - .name = "Traveler", - .protocol = &snd_motu_protocol_v2, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_HAS_AESEBU_IFACE | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | - SND_MOTU_SPEC_TX_MIDI_2ND_Q, - - .analog_in_ports = 8, - .analog_out_ports = 8, -}; - -static const struct snd_motu_spec motu_ultralite = { - .name = "UltraLite", - .protocol = &snd_motu_protocol_v2, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | // padding. - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | - SND_MOTU_SPEC_TX_MIDI_2ND_Q | - SND_MOTU_SPEC_RX_SEPARATED_MAIN, - .analog_in_ports = 8, - .analog_out_ports = 8, -}; - -static const struct snd_motu_spec motu_8pre = { - .name = "8pre", - .protocol = &snd_motu_protocol_v2, - // In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for - // dummy 1/2. - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | - SND_MOTU_SPEC_HAS_OPT_IFACE_B | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | - SND_MOTU_SPEC_TX_MIDI_2ND_Q, - .analog_in_ports = 8, - .analog_out_ports = 2, -}; - static const struct snd_motu_spec motu_828mk3 = { .name = "828mk3", .protocol = &snd_motu_protocol_v3, @@ -284,9 +227,9 @@ static const struct snd_motu_spec motu_4pre = { static const struct ieee1394_device_id motu_id_table[] = { SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2), - SND_MOTU_DEV_ENTRY(0x000009, &motu_traveler), - SND_MOTU_DEV_ENTRY(0x00000d, &motu_ultralite), - SND_MOTU_DEV_ENTRY(0x00000f, &motu_8pre), + SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler), + SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite), + SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre), SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */ SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */ SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express), diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 6efbde405a0d..ead6cc840d50 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -131,6 +131,9 @@ extern const struct snd_motu_protocol snd_motu_protocol_v2; extern const struct snd_motu_protocol snd_motu_protocol_v3; extern const struct snd_motu_spec snd_motu_spec_828mk2; +extern const struct snd_motu_spec snd_motu_spec_traveler; +extern const struct snd_motu_spec snd_motu_spec_ultralite; +extern const struct snd_motu_spec snd_motu_spec_8pre; int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, From c806a0e228318dec8384d765462764443bdc4786 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:29 +0900 Subject: [PATCH 333/428] ALSA: firewire-motu: move spec data to v3 protocol file The most of members in spec data is used in each protocol file. It's better to capsulate the data to the file. This commit moves the data to the file for protocol version 3. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-3-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v3.c | 42 ++++++++++++++++++++++ sound/firewire/motu/motu.c | 50 +++----------------------- sound/firewire/motu/motu.h | 4 +++ 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index d1545e2b5caa..947fab7905fe 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -314,3 +314,45 @@ const struct snd_motu_protocol snd_motu_protocol_v3 = { .switch_fetching_mode = v3_switch_fetching_mode, .cache_packet_formats = v3_cache_packet_formats, }; + +const struct snd_motu_spec snd_motu_spec_828mk3 = { + .name = "828mk3", + .protocol = &snd_motu_protocol_v3, + .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | + SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | + SND_MOTU_SPEC_TX_MICINST_CHUNK | + SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_TX_REVERB_CHUNK | + SND_MOTU_SPEC_RX_SEPARATED_MAIN | + SND_MOTU_SPEC_HAS_OPT_IFACE_A | + SND_MOTU_SPEC_HAS_OPT_IFACE_B | + SND_MOTU_SPEC_RX_MIDI_3RD_Q | + SND_MOTU_SPEC_TX_MIDI_3RD_Q, + + .analog_in_ports = 8, + .analog_out_ports = 8, +}; + +const struct snd_motu_spec snd_motu_spec_audio_express = { + .name = "AudioExpress", + .protocol = &snd_motu_protocol_v3, + .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | + SND_MOTU_SPEC_TX_MICINST_CHUNK | + SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_RX_SEPARATED_MAIN | + SND_MOTU_SPEC_RX_MIDI_2ND_Q | + SND_MOTU_SPEC_TX_MIDI_3RD_Q, + .analog_in_ports = 2, + .analog_out_ports = 4, +}; + +const struct snd_motu_spec snd_motu_spec_4pre = { + .name = "4pre", + .protocol = &snd_motu_protocol_v3, + .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | + SND_MOTU_SPEC_TX_MICINST_CHUNK | + SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_RX_SEPARATED_MAIN, + .analog_in_ports = 2, + .analog_out_ports = 2, +}; diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index b3533526f7e5..e5b6f634aa35 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c @@ -172,48 +172,6 @@ static void motu_bus_update(struct fw_unit *unit) snd_motu_transaction_reregister(motu); } -static const struct snd_motu_spec motu_828mk3 = { - .name = "828mk3", - .protocol = &snd_motu_protocol_v3, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_TX_REVERB_CHUNK | - SND_MOTU_SPEC_RX_SEPARATED_MAIN | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | - SND_MOTU_SPEC_HAS_OPT_IFACE_B | - SND_MOTU_SPEC_RX_MIDI_3RD_Q | - SND_MOTU_SPEC_TX_MIDI_3RD_Q, - - .analog_in_ports = 8, - .analog_out_ports = 8, -}; - -static const struct snd_motu_spec motu_audio_express = { - .name = "AudioExpress", - .protocol = &snd_motu_protocol_v3, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_RX_SEPARATED_MAIN | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | - SND_MOTU_SPEC_TX_MIDI_3RD_Q, - .analog_in_ports = 2, - .analog_out_ports = 4, -}; - -static const struct snd_motu_spec motu_4pre = { - .name = "4pre", - .protocol = &snd_motu_protocol_v3, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_RX_SEPARATED_MAIN, - .analog_in_ports = 2, - .analog_out_ports = 2, -}; - #define SND_MOTU_DEV_ENTRY(model, data) \ { \ .match_flags = IEEE1394_MATCH_VENDOR_ID | \ @@ -230,10 +188,10 @@ static const struct ieee1394_device_id motu_id_table[] = { SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler), SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite), SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre), - SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */ - SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */ - SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express), - SND_MOTU_DEV_ENTRY(0x000045, &motu_4pre), + SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3), // FireWire only. + SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3), // Hybrid. + SND_MOTU_DEV_ENTRY(0x000033, &snd_motu_spec_audio_express), + SND_MOTU_DEV_ENTRY(0x000045, &snd_motu_spec_4pre), { } }; MODULE_DEVICE_TABLE(ieee1394, motu_id_table); diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index ead6cc840d50..7774c23f1637 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -135,6 +135,10 @@ extern const struct snd_motu_spec snd_motu_spec_traveler; extern const struct snd_motu_spec snd_motu_spec_ultralite; extern const struct snd_motu_spec snd_motu_spec_8pre; +extern const struct snd_motu_spec snd_motu_spec_828mk3; +extern const struct snd_motu_spec snd_motu_spec_audio_express; +extern const struct snd_motu_spec snd_motu_spec_4pre; + int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, const struct snd_motu_protocol *const protocol); From 61d79c70c976a14cb321e537c39d147f7069e86a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:30 +0900 Subject: [PATCH 334/428] ALSA: firewire-motu: localize protocol data This commit adds enumerations of protocol version to localize protocol data. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-4-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/amdtp-motu.c | 7 ++++--- sound/firewire/motu/motu-protocol-v2.c | 6 +++++- sound/firewire/motu/motu-protocol-v3.c | 5 ++++- sound/firewire/motu/motu-stream.c | 2 +- sound/firewire/motu/motu.h | 11 +++++++---- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 0fd36e469ad0..17c9ea8eb4c8 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -440,7 +440,7 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, - const struct snd_motu_protocol *const protocol) + const struct snd_motu_spec *spec) { amdtp_stream_process_ctx_payloads_t process_ctx_payloads; int fmt = CIP_FMT_MOTU; @@ -454,14 +454,15 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, * Units of version 3 transmits packets with invalid CIP header * against IEC 61883-1. */ - if (protocol == &snd_motu_protocol_v3) { + if (spec->protocol_version == SND_MOTU_PROTOCOL_V3) { flags |= CIP_WRONG_DBS | CIP_SKIP_DBC_ZERO_CHECK | CIP_HEADER_WITHOUT_EOH; fmt = CIP_FMT_MOTU_TX_V3; } - if (protocol == &snd_motu_protocol_v2) { + if (spec == &snd_motu_spec_8pre || + spec == &snd_motu_spec_ultralite) { // 8pre has some quirks. flags |= CIP_WRONG_DBS | CIP_SKIP_DBC_ZERO_CHECK; diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index ed71c08e5942..2cd710a7c792 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -293,7 +293,7 @@ static int v2_cache_packet_formats(struct snd_motu *motu) return 0; } -const struct snd_motu_protocol snd_motu_protocol_v2 = { +static const struct snd_motu_protocol snd_motu_protocol_v2 = { .get_clock_rate = v2_get_clock_rate, .set_clock_rate = v2_set_clock_rate, .get_clock_source = v2_get_clock_source, @@ -303,6 +303,7 @@ const struct snd_motu_protocol snd_motu_protocol_v2 = { const struct snd_motu_spec snd_motu_spec_828mk2 = { .name = "828mk2", + .protocol_version = SND_MOTU_PROTOCOL_V2, .protocol = &snd_motu_protocol_v2, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | @@ -319,6 +320,7 @@ const struct snd_motu_spec snd_motu_spec_828mk2 = { const struct snd_motu_spec snd_motu_spec_traveler = { .name = "Traveler", .protocol = &snd_motu_protocol_v2, + .protocol_version = SND_MOTU_PROTOCOL_V2, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | SND_MOTU_SPEC_TX_RETURN_CHUNK | @@ -333,6 +335,7 @@ const struct snd_motu_spec snd_motu_spec_traveler = { const struct snd_motu_spec snd_motu_spec_ultralite = { .name = "UltraLite", + .protocol_version = SND_MOTU_PROTOCOL_V2, .protocol = &snd_motu_protocol_v2, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | // padding. @@ -346,6 +349,7 @@ const struct snd_motu_spec snd_motu_spec_ultralite = { const struct snd_motu_spec snd_motu_spec_8pre = { .name = "8pre", + .protocol_version = SND_MOTU_PROTOCOL_V2, .protocol = &snd_motu_protocol_v2, // In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for // dummy 1/2. diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 947fab7905fe..548c97752cb8 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -307,7 +307,7 @@ static int v3_cache_packet_formats(struct snd_motu *motu) return 0; } -const struct snd_motu_protocol snd_motu_protocol_v3 = { +static const struct snd_motu_protocol snd_motu_protocol_v3 = { .get_clock_rate = v3_get_clock_rate, .set_clock_rate = v3_set_clock_rate, .get_clock_source = v3_get_clock_source, @@ -317,6 +317,7 @@ const struct snd_motu_protocol snd_motu_protocol_v3 = { const struct snd_motu_spec snd_motu_spec_828mk3 = { .name = "828mk3", + .protocol_version = SND_MOTU_PROTOCOL_V3, .protocol = &snd_motu_protocol_v3, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | @@ -335,6 +336,7 @@ const struct snd_motu_spec snd_motu_spec_828mk3 = { const struct snd_motu_spec snd_motu_spec_audio_express = { .name = "AudioExpress", + .protocol_version = SND_MOTU_PROTOCOL_V3, .protocol = &snd_motu_protocol_v3, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | @@ -348,6 +350,7 @@ const struct snd_motu_spec snd_motu_spec_audio_express = { const struct snd_motu_spec snd_motu_spec_4pre = { .name = "4pre", + .protocol_version = SND_MOTU_PROTOCOL_V3, .protocol = &snd_motu_protocol_v3, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index a17ddceb1bec..11a2b8b37768 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -317,7 +317,7 @@ static int init_stream(struct snd_motu *motu, struct amdtp_stream *s) if (err < 0) return err; - err = amdtp_motu_init(s, motu->unit, dir, motu->spec->protocol); + err = amdtp_motu_init(s, motu->unit, dir, motu->spec); if (err < 0) fw_iso_resources_destroy(resources); diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 7774c23f1637..9db692006d95 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -108,6 +108,11 @@ enum snd_motu_clock_source { SND_MOTU_CLOCK_SOURCE_UNKNOWN, }; +enum snd_motu_protocol_version { + SND_MOTU_PROTOCOL_V2, + SND_MOTU_PROTOCOL_V3, +}; + struct snd_motu_protocol { int (*get_clock_rate)(struct snd_motu *motu, unsigned int *rate); int (*set_clock_rate)(struct snd_motu *motu, unsigned int rate); @@ -119,6 +124,7 @@ struct snd_motu_protocol { struct snd_motu_spec { const char *const name; + enum snd_motu_protocol_version protocol_version; enum snd_motu_spec_flags flags; unsigned char analog_in_ports; @@ -127,9 +133,6 @@ struct snd_motu_spec { const struct snd_motu_protocol *const protocol; }; -extern const struct snd_motu_protocol snd_motu_protocol_v2; -extern const struct snd_motu_protocol snd_motu_protocol_v3; - extern const struct snd_motu_spec snd_motu_spec_828mk2; extern const struct snd_motu_spec snd_motu_spec_traveler; extern const struct snd_motu_spec snd_motu_spec_ultralite; @@ -141,7 +144,7 @@ extern const struct snd_motu_spec snd_motu_spec_4pre; int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, - const struct snd_motu_protocol *const protocol); + const struct snd_motu_spec *spec); int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate, unsigned int midi_ports, struct snd_motu_packet_format *formats); From ff222b7e45eb1ffb2931269abf66b9d3576c9eeb Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:31 +0900 Subject: [PATCH 335/428] ALSA: firewire-motu: add wrapper functions for protocol-dependent operations This commit adds helper functions which wraps function call for each protocol. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-5-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-pcm.c | 5 +- sound/firewire/motu/motu-proc.c | 8 ++- sound/firewire/motu/motu-protocol-v2.c | 20 ++++--- sound/firewire/motu/motu-protocol-v3.c | 20 ++++--- sound/firewire/motu/motu-stream.c | 10 ++-- sound/firewire/motu/motu.h | 75 ++++++++++++++++++++++++++ 6 files changed, 103 insertions(+), 35 deletions(-) diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index 2d41a1a4052c..b24bb870388e 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -133,7 +133,6 @@ static int init_hw_info(struct snd_motu *motu, static int pcm_open(struct snd_pcm_substream *substream) { struct snd_motu *motu = substream->private_data; - const struct snd_motu_protocol *const protocol = motu->spec->protocol; struct amdtp_domain *d = &motu->domain; enum snd_motu_clock_source src; int err; @@ -152,7 +151,7 @@ static int pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto err_locked; - err = protocol->get_clock_source(motu, &src); + err = snd_motu_protocol_get_clock_source(motu, &src); if (err < 0) goto err_locked; @@ -166,7 +165,7 @@ static int pcm_open(struct snd_pcm_substream *substream) unsigned int frames_per_buffer = d->events_per_buffer; unsigned int rate; - err = protocol->get_clock_rate(motu, &rate); + err = snd_motu_protocol_get_clock_rate(motu, &rate); if (err < 0) goto err_locked; diff --git a/sound/firewire/motu/motu-proc.c b/sound/firewire/motu/motu-proc.c index 187f6abd878c..71d02602d84d 100644 --- a/sound/firewire/motu/motu-proc.c +++ b/sound/firewire/motu/motu-proc.c @@ -28,13 +28,12 @@ static void proc_read_clock(struct snd_info_entry *entry, { struct snd_motu *motu = entry->private_data; - const struct snd_motu_protocol *const protocol = motu->spec->protocol; unsigned int rate; enum snd_motu_clock_source source; - if (protocol->get_clock_rate(motu, &rate) < 0) + if (snd_motu_protocol_get_clock_rate(motu, &rate) < 0) return; - if (protocol->get_clock_source(motu, &source) < 0) + if (snd_motu_protocol_get_clock_source(motu, &source) < 0) return; snd_iprintf(buffer, "Rate:\t%d\n", rate); @@ -45,12 +44,11 @@ static void proc_read_format(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_motu *motu = entry->private_data; - const struct snd_motu_protocol *const protocol = motu->spec->protocol; unsigned int mode; struct snd_motu_packet_format *formats; int i; - if (protocol->cache_packet_formats(motu) < 0) + if (snd_motu_protocol_cache_packet_formats(motu) < 0) return; snd_iprintf(buffer, "tx:\tmsg\tfixed\tdiffered\n"); diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 2cd710a7c792..26534ed97fbc 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -35,7 +35,8 @@ static int get_clock_rate(u32 data, unsigned int *rate) return 0; } -static int v2_get_clock_rate(struct snd_motu *motu, unsigned int *rate) +int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu, + unsigned int *rate) { __be32 reg; int err; @@ -48,7 +49,8 @@ static int v2_get_clock_rate(struct snd_motu *motu, unsigned int *rate) return get_clock_rate(be32_to_cpu(reg), rate); } -static int v2_set_clock_rate(struct snd_motu *motu, unsigned int rate) +int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu, + unsigned int rate) { __be32 reg; u32 data; @@ -122,8 +124,8 @@ static int get_clock_source(struct snd_motu *motu, u32 data, return 0; } -static int v2_get_clock_source(struct snd_motu *motu, - enum snd_motu_clock_source *src) +int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu, + enum snd_motu_clock_source *src) { __be32 reg; int err; @@ -136,7 +138,8 @@ static int v2_get_clock_source(struct snd_motu *motu, return get_clock_source(motu, be32_to_cpu(reg), src); } -static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable) +int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu, + bool enable) { enum snd_motu_clock_source src; __be32 reg; @@ -265,7 +268,7 @@ static void calculate_differed_part(struct snd_motu_packet_format *formats, formats->differed_part_pcm_chunks[1] = pcm_chunks[1]; } -static int v2_cache_packet_formats(struct snd_motu *motu) +int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) { __be32 reg; u32 data; @@ -294,11 +297,6 @@ static int v2_cache_packet_formats(struct snd_motu *motu) } static const struct snd_motu_protocol snd_motu_protocol_v2 = { - .get_clock_rate = v2_get_clock_rate, - .set_clock_rate = v2_set_clock_rate, - .get_clock_source = v2_get_clock_source, - .switch_fetching_mode = v2_switch_fetching_mode, - .cache_packet_formats = v2_cache_packet_formats, }; const struct snd_motu_spec snd_motu_spec_828mk2 = { diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 548c97752cb8..d8b42d28304a 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -24,7 +24,8 @@ #define V3_NO_ADAT_OPT_OUT_IFACE_A 0x00040000 #define V3_NO_ADAT_OPT_OUT_IFACE_B 0x00400000 -static int v3_get_clock_rate(struct snd_motu *motu, unsigned int *rate) +int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu, + unsigned int *rate) { __be32 reg; u32 data; @@ -45,7 +46,8 @@ static int v3_get_clock_rate(struct snd_motu *motu, unsigned int *rate) return 0; } -static int v3_set_clock_rate(struct snd_motu *motu, unsigned int rate) +int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu, + unsigned int rate) { __be32 reg; u32 data; @@ -85,8 +87,8 @@ static int v3_set_clock_rate(struct snd_motu *motu, unsigned int rate) return 0; } -static int v3_get_clock_source(struct snd_motu *motu, - enum snd_motu_clock_source *src) +int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu, + enum snd_motu_clock_source *src) { __be32 reg; u32 data; @@ -133,7 +135,8 @@ static int v3_get_clock_source(struct snd_motu *motu, return 0; } -static int v3_switch_fetching_mode(struct snd_motu *motu, bool enable) +int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu, + bool enable) { __be32 reg; u32 data; @@ -275,7 +278,7 @@ static void calculate_differed_part(struct snd_motu_packet_format *formats, } } -static int v3_cache_packet_formats(struct snd_motu *motu) +int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) { __be32 reg; u32 data; @@ -308,11 +311,6 @@ static int v3_cache_packet_formats(struct snd_motu *motu) } static const struct snd_motu_protocol snd_motu_protocol_v3 = { - .get_clock_rate = v3_get_clock_rate, - .set_clock_rate = v3_set_clock_rate, - .get_clock_source = v3_get_clock_source, - .switch_fetching_mode = v3_switch_fetching_mode, - .cache_packet_formats = v3_cache_packet_formats, }; const struct snd_motu_spec snd_motu_spec_828mk3 = { diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 11a2b8b37768..87a8d9016f83 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -88,7 +88,7 @@ static void finish_session(struct snd_motu *motu) u32 data; int err; - err = motu->spec->protocol->switch_fetching_mode(motu, false); + err = snd_motu_protocol_switch_fetching_mode(motu, false); if (err < 0) return; @@ -110,7 +110,7 @@ int snd_motu_stream_cache_packet_formats(struct snd_motu *motu) { int err; - err = motu->spec->protocol->cache_packet_formats(motu); + err = snd_motu_protocol_cache_packet_formats(motu); if (err < 0) return err; @@ -140,7 +140,7 @@ 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); + err = snd_motu_protocol_get_clock_rate(motu, &curr_rate); if (err < 0) return err; if (rate == 0) @@ -153,7 +153,7 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate, fw_iso_resources_free(&motu->tx_resources); fw_iso_resources_free(&motu->rx_resources); - err = motu->spec->protocol->set_clock_rate(motu, rate); + err = snd_motu_protocol_set_clock_rate(motu, rate); if (err < 0) { dev_err(&motu->unit->device, "fail to set sampling rate: %d\n", err); @@ -272,7 +272,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) goto stop_streams; } - err = motu->spec->protocol->switch_fetching_mode(motu, true); + err = snd_motu_protocol_switch_fetching_mode(motu, true); if (err < 0) { dev_err(&motu->unit->device, "fail to enable frame fetching: %d\n", err); diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 9db692006d95..d59841677596 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -179,4 +179,79 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu); int snd_motu_create_midi_devices(struct snd_motu *motu); int snd_motu_create_hwdep_device(struct snd_motu *motu); + +int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu, + unsigned int *rate); +int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu, + unsigned int rate); +int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu, + enum snd_motu_clock_source *src); +int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu, + bool enable); +int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu); + +int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu, + unsigned int *rate); +int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu, + unsigned int rate); +int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu, + enum snd_motu_clock_source *src); +int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu, + bool enable); +int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu); + +static inline int snd_motu_protocol_get_clock_rate(struct snd_motu *motu, + unsigned int *rate) +{ + if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2) + return snd_motu_protocol_v2_get_clock_rate(motu, rate); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) + return snd_motu_protocol_v3_get_clock_rate(motu, rate); + else + return -ENXIO; +} + +static inline int snd_motu_protocol_set_clock_rate(struct snd_motu *motu, + unsigned int rate) +{ + if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2) + return snd_motu_protocol_v2_set_clock_rate(motu, rate); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) + return snd_motu_protocol_v3_set_clock_rate(motu, rate); + else + return -ENXIO; +} + +static inline int snd_motu_protocol_get_clock_source(struct snd_motu *motu, + enum snd_motu_clock_source *source) +{ + if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2) + return snd_motu_protocol_v2_get_clock_source(motu, source); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) + return snd_motu_protocol_v3_get_clock_source(motu, source); + else + return -ENXIO; +} + +static inline int snd_motu_protocol_switch_fetching_mode(struct snd_motu *motu, + bool enable) +{ + if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2) + return snd_motu_protocol_v2_switch_fetching_mode(motu, enable); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) + return snd_motu_protocol_v3_switch_fetching_mode(motu, enable); + else + return -ENXIO; +} + +static inline int snd_motu_protocol_cache_packet_formats(struct snd_motu *motu) +{ + if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2) + return snd_motu_protocol_v2_cache_packet_formats(motu); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) + return snd_motu_protocol_v3_cache_packet_formats(motu); + else + return -ENXIO; +} + #endif From 562f0c6700cfeb28b7a95d4b7cb6b0496d0b2fb5 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:32 +0900 Subject: [PATCH 336/428] ALSA: firewire-motu: drop protocol structure Now protocol structure becomes useless. This commit drops it. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-6-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 7 ------- sound/firewire/motu/motu-protocol-v3.c | 5 ----- sound/firewire/motu/motu.h | 11 ----------- 3 files changed, 23 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 26534ed97fbc..e2913cb54da8 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -296,13 +296,9 @@ int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) return 0; } -static const struct snd_motu_protocol snd_motu_protocol_v2 = { -}; - const struct snd_motu_spec snd_motu_spec_828mk2 = { .name = "828mk2", .protocol_version = SND_MOTU_PROTOCOL_V2, - .protocol = &snd_motu_protocol_v2, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | SND_MOTU_SPEC_TX_RETURN_CHUNK | @@ -317,7 +313,6 @@ const struct snd_motu_spec snd_motu_spec_828mk2 = { const struct snd_motu_spec snd_motu_spec_traveler = { .name = "Traveler", - .protocol = &snd_motu_protocol_v2, .protocol_version = SND_MOTU_PROTOCOL_V2, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | @@ -334,7 +329,6 @@ const struct snd_motu_spec snd_motu_spec_traveler = { const struct snd_motu_spec snd_motu_spec_ultralite = { .name = "UltraLite", .protocol_version = SND_MOTU_PROTOCOL_V2, - .protocol = &snd_motu_protocol_v2, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | // padding. SND_MOTU_SPEC_TX_RETURN_CHUNK | @@ -348,7 +342,6 @@ const struct snd_motu_spec snd_motu_spec_ultralite = { const struct snd_motu_spec snd_motu_spec_8pre = { .name = "8pre", .protocol_version = SND_MOTU_PROTOCOL_V2, - .protocol = &snd_motu_protocol_v2, // In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for // dummy 1/2. .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index d8b42d28304a..8192bcdd1b37 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -310,13 +310,10 @@ int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) return 0; } -static const struct snd_motu_protocol snd_motu_protocol_v3 = { -}; const struct snd_motu_spec snd_motu_spec_828mk3 = { .name = "828mk3", .protocol_version = SND_MOTU_PROTOCOL_V3, - .protocol = &snd_motu_protocol_v3, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | SND_MOTU_SPEC_TX_MICINST_CHUNK | @@ -335,7 +332,6 @@ const struct snd_motu_spec snd_motu_spec_828mk3 = { const struct snd_motu_spec snd_motu_spec_audio_express = { .name = "AudioExpress", .protocol_version = SND_MOTU_PROTOCOL_V3, - .protocol = &snd_motu_protocol_v3, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | SND_MOTU_SPEC_TX_RETURN_CHUNK | @@ -349,7 +345,6 @@ const struct snd_motu_spec snd_motu_spec_audio_express = { const struct snd_motu_spec snd_motu_spec_4pre = { .name = "4pre", .protocol_version = SND_MOTU_PROTOCOL_V3, - .protocol = &snd_motu_protocol_v3, .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | SND_MOTU_SPEC_TX_RETURN_CHUNK | diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index d59841677596..f8274ed94766 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -113,15 +113,6 @@ enum snd_motu_protocol_version { SND_MOTU_PROTOCOL_V3, }; -struct snd_motu_protocol { - int (*get_clock_rate)(struct snd_motu *motu, unsigned int *rate); - int (*set_clock_rate)(struct snd_motu *motu, unsigned int rate); - int (*get_clock_source)(struct snd_motu *motu, - enum snd_motu_clock_source *source); - int (*switch_fetching_mode)(struct snd_motu *motu, bool enable); - int (*cache_packet_formats)(struct snd_motu *motu); -}; - struct snd_motu_spec { const char *const name; enum snd_motu_protocol_version protocol_version; @@ -129,8 +120,6 @@ struct snd_motu_spec { unsigned char analog_in_ports; unsigned char analog_out_ports; - - const struct snd_motu_protocol *const protocol; }; extern const struct snd_motu_spec snd_motu_spec_828mk2; From dfbaa4dc11eb93e3662dcefbf00a14235c4c1e8e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:33 +0900 Subject: [PATCH 337/428] ALSA: firewire-motu: add model-specific table of chunk count In MOTU protocol, data block consists of SPH and 24-bit chunks aligned to quadlet. The number of chunks per data block is specific to model. For models with optical interface, the number differs depending on I/O settings for the interface (ADAT, TOSLINK). Currently the number is calculated from flags in model-specific data. However this is weak in the case that the model has quirks. Actually, for quirks of some models, flags are used against their original meanings. This commit adds model-specific table of chunk count. For future integration, this table is based on the calculation. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-7-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 10 ++++++++-- sound/firewire/motu/motu-protocol-v3.c | 7 ++++++- sound/firewire/motu/motu.h | 3 +++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index e2913cb54da8..6cd7a5f1f46c 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -306,7 +306,8 @@ const struct snd_motu_spec snd_motu_spec_828mk2 = { SND_MOTU_SPEC_HAS_OPT_IFACE_A | SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, - + .tx_fixed_pcm_chunks = {14, 14, 0}, + .rx_fixed_pcm_chunks = {14, 14, 0}, .analog_in_ports = 8, .analog_out_ports = 8, }; @@ -321,7 +322,8 @@ const struct snd_motu_spec snd_motu_spec_traveler = { SND_MOTU_SPEC_HAS_OPT_IFACE_A | SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, - + .tx_fixed_pcm_chunks = {14, 14, 8}, + .rx_fixed_pcm_chunks = {14, 14, 8}, .analog_in_ports = 8, .analog_out_ports = 8, }; @@ -335,6 +337,8 @@ const struct snd_motu_spec snd_motu_spec_ultralite = { SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q | SND_MOTU_SPEC_RX_SEPARATED_MAIN, + .tx_fixed_pcm_chunks = {14, 14, 0}, + .rx_fixed_pcm_chunks = {14, 14, 0}, .analog_in_ports = 8, .analog_out_ports = 8, }; @@ -349,6 +353,8 @@ const struct snd_motu_spec snd_motu_spec_8pre = { SND_MOTU_SPEC_HAS_OPT_IFACE_B | SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, + .tx_fixed_pcm_chunks = {10, 6, 0}, + .rx_fixed_pcm_chunks = {10, 6, 0}, .analog_in_ports = 8, .analog_out_ports = 2, }; diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 8192bcdd1b37..370d22da276e 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -324,7 +324,8 @@ const struct snd_motu_spec snd_motu_spec_828mk3 = { SND_MOTU_SPEC_HAS_OPT_IFACE_B | SND_MOTU_SPEC_RX_MIDI_3RD_Q | SND_MOTU_SPEC_TX_MIDI_3RD_Q, - + .tx_fixed_pcm_chunks = {18, 18, 14}, + .rx_fixed_pcm_chunks = {14, 14, 10}, .analog_in_ports = 8, .analog_out_ports = 8, }; @@ -338,6 +339,8 @@ const struct snd_motu_spec snd_motu_spec_audio_express = { SND_MOTU_SPEC_RX_SEPARATED_MAIN | SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_3RD_Q, + .tx_fixed_pcm_chunks = {10, 10, 0}, + .rx_fixed_pcm_chunks = {10, 10, 0}, .analog_in_ports = 2, .analog_out_ports = 4, }; @@ -349,6 +352,8 @@ const struct snd_motu_spec snd_motu_spec_4pre = { SND_MOTU_SPEC_TX_MICINST_CHUNK | SND_MOTU_SPEC_TX_RETURN_CHUNK | SND_MOTU_SPEC_RX_SEPARATED_MAIN, + .tx_fixed_pcm_chunks = {10, 10, 0}, + .rx_fixed_pcm_chunks = {10, 10, 0}, .analog_in_ports = 2, .analog_out_ports = 2, }; diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index f8274ed94766..790aa34d396f 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -118,6 +118,9 @@ struct snd_motu_spec { enum snd_motu_protocol_version protocol_version; enum snd_motu_spec_flags flags; + unsigned char tx_fixed_pcm_chunks[3]; + unsigned char rx_fixed_pcm_chunks[3]; + unsigned char analog_in_ports; unsigned char analog_out_ports; }; From 28c8d3c91af79de34b2ea540b5385b2da4999e80 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:34 +0900 Subject: [PATCH 338/428] ALSA: firewire-motu: add alternative functions to detect packet format for protocol v2 This commit adds alternative functions to detect packet format so that each function corresponds to each model. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-8-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 72 +++++++++++++++++++++++--- sound/firewire/motu/motu.h | 1 + 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 6cd7a5f1f46c..cd409efe3350 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -164,7 +164,7 @@ int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu, if (enable) data |= V2_CLOCK_FETCH_ENABLE; - if (motu->spec->flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) { + if (motu->spec == &snd_motu_spec_traveler) { // Expected for Traveler and 896HD, which implements Altera // Cyclone EP1C3. data |= V2_CLOCK_MODEL_SPECIFIC; @@ -193,8 +193,6 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats, { unsigned char pcm_chunks[3] = {0, 0, 0}; - formats->msg_chunks = 2; - pcm_chunks[0] = analog_ports; pcm_chunks[1] = analog_ports; if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) @@ -268,12 +266,69 @@ static void calculate_differed_part(struct snd_motu_packet_format *formats, formats->differed_part_pcm_chunks[1] = pcm_chunks[1]; } +static int detect_packet_formats_828mk2(struct snd_motu *motu, u32 data) +{ + if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == + V2_OPT_IFACE_MODE_ADAT) { + motu->tx_packet_formats.pcm_chunks[0] += 8; + motu->tx_packet_formats.pcm_chunks[1] += 4; + } + + if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) == + V2_OPT_IFACE_MODE_ADAT) { + motu->rx_packet_formats.pcm_chunks[0] += 8; + motu->rx_packet_formats.pcm_chunks[1] += 4; + } + + return 0; +} + +static int detect_packet_formats_traveler(struct snd_motu *motu, u32 data) +{ + if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == + V2_OPT_IFACE_MODE_ADAT) { + motu->tx_packet_formats.pcm_chunks[0] += 8; + motu->tx_packet_formats.pcm_chunks[1] += 4; + } + + if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) == + V2_OPT_IFACE_MODE_ADAT) { + motu->rx_packet_formats.pcm_chunks[0] += 8; + motu->rx_packet_formats.pcm_chunks[1] += 4; + } + + return 0; +} + +static int detect_packet_formats_8pre(struct snd_motu *motu, u32 data) +{ + if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == + V2_OPT_IFACE_MODE_ADAT) { + motu->tx_packet_formats.pcm_chunks[0] += 8; + motu->tx_packet_formats.pcm_chunks[1] += 8; + } + + if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) == + V2_OPT_IFACE_MODE_ADAT) { + motu->rx_packet_formats.pcm_chunks[0] += 8; + motu->rx_packet_formats.pcm_chunks[1] += 8; + } + + return 0; +} + int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) { __be32 reg; u32 data; int err; + motu->tx_packet_formats.pcm_byte_offset = 10; + motu->rx_packet_formats.pcm_byte_offset = 10; + + motu->tx_packet_formats.msg_chunks = 2; + motu->rx_packet_formats.msg_chunks = 2; + err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, ®, sizeof(reg)); if (err < 0) @@ -290,10 +345,15 @@ int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) calculate_differed_part(&motu->rx_packet_formats, motu->spec->flags, data, V2_OPT_OUT_IFACE_MASK, V2_OPT_OUT_IFACE_SHIFT); - motu->tx_packet_formats.pcm_byte_offset = 10; - motu->rx_packet_formats.pcm_byte_offset = 10; - return 0; + if (motu->spec == &snd_motu_spec_828mk2) + return detect_packet_formats_828mk2(motu, data); + else if (motu->spec == &snd_motu_spec_traveler) + return detect_packet_formats_traveler(motu, data); + else if (motu->spec == &snd_motu_spec_8pre) + return detect_packet_formats_8pre(motu, data); + else + return 0; } const struct snd_motu_spec snd_motu_spec_828mk2 = { diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 790aa34d396f..d071b2342f11 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -36,6 +36,7 @@ struct snd_motu_packet_format { unsigned char pcm_byte_offset; unsigned char msg_chunks; + unsigned char pcm_chunks[3]; unsigned char fixed_part_pcm_chunks[3]; unsigned char differed_part_pcm_chunks[3]; }; From 0090c1c5f327da077f371f5f8675a576bca6ebf9 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:35 +0900 Subject: [PATCH 339/428] ALSA: firewire-motu: add alternative functions to detect packet format for protocol v3 This commit adds alternative functions to detect packet format so that each function corresponds to each model. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-9-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 6 +++ sound/firewire/motu/motu-protocol-v3.c | 66 ++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index cd409efe3350..2ed800ccf6a2 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -345,6 +345,12 @@ int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) calculate_differed_part(&motu->rx_packet_formats, motu->spec->flags, data, V2_OPT_OUT_IFACE_MASK, V2_OPT_OUT_IFACE_SHIFT); + memcpy(motu->tx_packet_formats.pcm_chunks, + motu->spec->tx_fixed_pcm_chunks, + sizeof(motu->tx_packet_formats.pcm_chunks)); + memcpy(motu->rx_packet_formats.pcm_chunks, + motu->spec->rx_fixed_pcm_chunks, + sizeof(motu->rx_packet_formats.pcm_chunks)); if (motu->spec == &snd_motu_spec_828mk2) return detect_packet_formats_828mk2(motu, data); diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 370d22da276e..903a7eb209f9 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -165,8 +165,6 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats, { unsigned char pcm_chunks[3] = {0, 0, 0}; - formats->msg_chunks = 2; - pcm_chunks[0] = analog_ports; pcm_chunks[1] = analog_ports; if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) @@ -278,12 +276,63 @@ static void calculate_differed_part(struct snd_motu_packet_format *formats, } } +static int detect_packet_formats_828mk3(struct snd_motu *motu, u32 data) +{ + if (data & V3_ENABLE_OPT_IN_IFACE_A) { + if (data & V3_NO_ADAT_OPT_IN_IFACE_A) { + motu->tx_packet_formats.pcm_chunks[0] += 4; + motu->tx_packet_formats.pcm_chunks[1] += 4; + } else { + motu->tx_packet_formats.pcm_chunks[0] += 8; + motu->tx_packet_formats.pcm_chunks[1] += 4; + } + } + + if (data & V3_ENABLE_OPT_IN_IFACE_B) { + if (data & V3_NO_ADAT_OPT_IN_IFACE_B) { + motu->tx_packet_formats.pcm_chunks[0] += 4; + motu->tx_packet_formats.pcm_chunks[1] += 4; + } else { + motu->tx_packet_formats.pcm_chunks[0] += 8; + motu->tx_packet_formats.pcm_chunks[1] += 4; + } + } + + if (data & V3_ENABLE_OPT_OUT_IFACE_A) { + if (data & V3_NO_ADAT_OPT_OUT_IFACE_A) { + motu->rx_packet_formats.pcm_chunks[0] += 4; + motu->rx_packet_formats.pcm_chunks[1] += 4; + } else { + motu->rx_packet_formats.pcm_chunks[0] += 8; + motu->rx_packet_formats.pcm_chunks[1] += 4; + } + } + + if (data & V3_ENABLE_OPT_OUT_IFACE_B) { + if (data & V3_NO_ADAT_OPT_OUT_IFACE_B) { + motu->rx_packet_formats.pcm_chunks[0] += 4; + motu->rx_packet_formats.pcm_chunks[1] += 4; + } else { + motu->rx_packet_formats.pcm_chunks[0] += 8; + motu->rx_packet_formats.pcm_chunks[1] += 4; + } + } + + return 0; +} + int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) { __be32 reg; u32 data; int err; + motu->tx_packet_formats.pcm_byte_offset = 10; + motu->rx_packet_formats.pcm_byte_offset = 10; + + motu->tx_packet_formats.msg_chunks = 2; + motu->rx_packet_formats.msg_chunks = 2; + err = snd_motu_transaction_read(motu, V3_OPT_IFACE_MODE_OFFSET, ®, sizeof(reg)); if (err < 0) @@ -304,10 +353,17 @@ int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) V3_ENABLE_OPT_OUT_IFACE_A, V3_NO_ADAT_OPT_OUT_IFACE_A, V3_ENABLE_OPT_OUT_IFACE_B, V3_NO_ADAT_OPT_OUT_IFACE_B); - motu->tx_packet_formats.pcm_byte_offset = 10; - motu->rx_packet_formats.pcm_byte_offset = 10; + memcpy(motu->tx_packet_formats.pcm_chunks, + motu->spec->tx_fixed_pcm_chunks, + sizeof(motu->tx_packet_formats.pcm_chunks)); + memcpy(motu->rx_packet_formats.pcm_chunks, + motu->spec->rx_fixed_pcm_chunks, + sizeof(motu->rx_packet_formats.pcm_chunks)); - return 0; + if (motu->spec == &snd_motu_spec_828mk3) + return detect_packet_formats_828mk3(motu, data); + else + return 0; } From 9883b3850fba6c2842a15ac3b38e36b214e03ddf Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:36 +0900 Subject: [PATCH 340/428] ALSA: firewire-motu: use table-based calculation of packet formats for proc This commit uses table-based calculation of packet formats for proc nodes. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-10-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-pcm.c | 9 +++------ sound/firewire/motu/motu-proc.c | 12 ++++++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index b24bb870388e..8e1437371263 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -26,8 +26,7 @@ static int motu_rate_constraint(struct snd_pcm_hw_params *params, rate = snd_motu_clock_rates[i]; mode = i / 2; - pcm_channels = formats->fixed_part_pcm_chunks[mode] + - formats->differed_part_pcm_chunks[mode]; + pcm_channels = formats->pcm_chunks[mode]; if (!snd_interval_test(c, pcm_channels)) continue; @@ -59,8 +58,7 @@ static int motu_channels_constraint(struct snd_pcm_hw_params *params, if (!snd_interval_test(r, rate)) continue; - pcm_channels = formats->fixed_part_pcm_chunks[mode] + - formats->differed_part_pcm_chunks[mode]; + pcm_channels = formats->pcm_chunks[mode]; channels.min = min(channels.min, pcm_channels); channels.max = max(channels.max, pcm_channels); } @@ -82,8 +80,7 @@ static void limit_channels_and_rates(struct snd_motu *motu, rate = snd_motu_clock_rates[i]; mode = i / 2; - pcm_channels = formats->fixed_part_pcm_chunks[mode] + - formats->differed_part_pcm_chunks[mode]; + pcm_channels = formats->pcm_chunks[mode]; if (pcm_channels == 0) continue; diff --git a/sound/firewire/motu/motu-proc.c b/sound/firewire/motu/motu-proc.c index 71d02602d84d..f009cf7aa074 100644 --- a/sound/firewire/motu/motu-proc.c +++ b/sound/firewire/motu/motu-proc.c @@ -51,7 +51,7 @@ static void proc_read_format(struct snd_info_entry *entry, if (snd_motu_protocol_cache_packet_formats(motu) < 0) return; - snd_iprintf(buffer, "tx:\tmsg\tfixed\tdiffered\n"); + snd_iprintf(buffer, "tx:\tmsg\tfixed\ttotal\n"); for (i = 0; i < SND_MOTU_CLOCK_RATE_COUNT; ++i) { mode = i >> 1; @@ -60,11 +60,11 @@ static void proc_read_format(struct snd_info_entry *entry, "%u:\t%u\t%u\t%u\n", snd_motu_clock_rates[i], formats->msg_chunks, - formats->fixed_part_pcm_chunks[mode], - formats->differed_part_pcm_chunks[mode]); + motu->spec->tx_fixed_pcm_chunks[mode], + formats->pcm_chunks[mode]); } - snd_iprintf(buffer, "rx:\tmsg\tfixed\tdiffered\n"); + snd_iprintf(buffer, "rx:\tmsg\tfixed\ttotal\n"); for (i = 0; i < SND_MOTU_CLOCK_RATE_COUNT; ++i) { mode = i >> 1; @@ -73,8 +73,8 @@ static void proc_read_format(struct snd_info_entry *entry, "%u:\t%u\t%u\t%u\n", snd_motu_clock_rates[i], formats->msg_chunks, - formats->fixed_part_pcm_chunks[mode], - formats->differed_part_pcm_chunks[mode]); + motu->spec->rx_fixed_pcm_chunks[mode], + formats->pcm_chunks[mode]); } } From 88e8f89dcc66eafcd4c11fd41988ebe22b793df1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:37 +0900 Subject: [PATCH 341/428] ALSA: firewire-motu: use table-based calculation of packet formats for stream management This commit uses table-based calculation of packet formats for stream management. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-11-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/amdtp-motu.c | 12 ++++-------- sound/firewire/motu/motu-stream.c | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 17c9ea8eb4c8..edb31ac26868 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -76,15 +76,11 @@ int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate, if (i == ARRAY_SIZE(snd_motu_clock_rates)) return -EINVAL; - pcm_chunks = formats->fixed_part_pcm_chunks[mode] + - formats->differed_part_pcm_chunks[mode]; + // Each data block includes SPH in its head. Data chunks follow with + // 3 byte alignment. Padding follows with zero to conform to quadlet + // alignment. + pcm_chunks = formats->pcm_chunks[mode]; data_chunks = formats->msg_chunks + pcm_chunks; - - /* - * Each data block includes SPH in its head. Data chunks follow with - * 3 byte alignment. Padding follows with zero to conform to quadlet - * alignment. - */ data_block_quadlets = 1 + DIV_ROUND_UP(data_chunks * 3, 4); err = amdtp_stream_set_parameters(s, rate, data_block_quadlets); diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 87a8d9016f83..2028c5419f6f 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -201,9 +201,9 @@ static int ensure_packet_formats(struct snd_motu *motu) data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS | RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS| TX_PACKET_TRANSMISSION_SPEED_MASK); - if (motu->tx_packet_formats.differed_part_pcm_chunks[0] == 0) + if (motu->spec->tx_fixed_pcm_chunks[0] == motu->tx_packet_formats.pcm_chunks[0]) data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS; - if (motu->rx_packet_formats.differed_part_pcm_chunks[0] == 0) + if (motu->spec->rx_fixed_pcm_chunks[0] == motu->rx_packet_formats.pcm_chunks[0]) data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS; data |= fw_parent_device(motu->unit)->max_speed; From 739bdbaec76ae7e6e2de80c06e1d4ca31e7c96b9 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:38 +0900 Subject: [PATCH 342/428] ALSA: firewire-motu: remove obsoleted codes The way to decide CIP payload size by calculation with any flag is now obsoleted. This commit removes the codes. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-12-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 127 +------------------- sound/firewire/motu/motu-protocol-v3.c | 158 +------------------------ sound/firewire/motu/motu.h | 22 +--- 3 files changed, 11 insertions(+), 296 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 2ed800ccf6a2..1bdc905e8e22 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -186,86 +186,6 @@ int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu, sizeof(reg)); } -static void calculate_fixed_part(struct snd_motu_packet_format *formats, - enum amdtp_stream_direction dir, - enum snd_motu_spec_flags flags, - unsigned char analog_ports) -{ - unsigned char pcm_chunks[3] = {0, 0, 0}; - - pcm_chunks[0] = analog_ports; - pcm_chunks[1] = analog_ports; - if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) - pcm_chunks[2] = analog_ports; - - if (dir == AMDTP_IN_STREAM) { - if (flags & SND_MOTU_SPEC_TX_MICINST_CHUNK) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - if (flags & SND_MOTU_SPEC_TX_RETURN_CHUNK) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - } else { - if (flags & SND_MOTU_SPEC_RX_SEPARATED_MAIN) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - - // Packets to v2 units include 2 chunks for phone 1/2, except - // for 176.4/192.0 kHz. - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - - if (flags & SND_MOTU_SPEC_HAS_AESEBU_IFACE) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - - /* - * All of v2 models have a pair of coaxial interfaces for digital in/out - * port. At 44.1/48.0/88.2/96.0 kHz, packets includes PCM from these - * ports. - */ - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - - formats->fixed_part_pcm_chunks[0] = pcm_chunks[0]; - formats->fixed_part_pcm_chunks[1] = pcm_chunks[1]; - formats->fixed_part_pcm_chunks[2] = pcm_chunks[2]; -} - -static void calculate_differed_part(struct snd_motu_packet_format *formats, - enum snd_motu_spec_flags flags, - u32 data, u32 mask, u32 shift) -{ - unsigned char pcm_chunks[2] = {0, 0}; - - /* - * When optical interfaces are configured for S/PDIF (TOSLINK), - * the above PCM frames come from them, instead of coaxial - * interfaces. - */ - data = (data & mask) >> shift; - if (data == V2_OPT_IFACE_MODE_ADAT) { - if (flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) { - pcm_chunks[0] += 8; - pcm_chunks[1] += 4; - } - // 8pre has two sets of optical interface and doesn't reduce - // chunks for ADAT signals. - if (flags & SND_MOTU_SPEC_HAS_OPT_IFACE_B) { - pcm_chunks[1] += 4; - } - } - - /* At mode x4, no data chunks are supported in this part. */ - formats->differed_part_pcm_chunks[0] = pcm_chunks[0]; - formats->differed_part_pcm_chunks[1] = pcm_chunks[1]; -} - static int detect_packet_formats_828mk2(struct snd_motu *motu, u32 data) { if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == @@ -335,16 +255,6 @@ int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) return err; data = be32_to_cpu(reg); - calculate_fixed_part(&motu->tx_packet_formats, AMDTP_IN_STREAM, - motu->spec->flags, motu->spec->analog_in_ports); - calculate_differed_part(&motu->tx_packet_formats, motu->spec->flags, - data, V2_OPT_IN_IFACE_MASK, V2_OPT_IN_IFACE_SHIFT); - - calculate_fixed_part(&motu->rx_packet_formats, AMDTP_OUT_STREAM, - motu->spec->flags, motu->spec->analog_out_ports); - calculate_differed_part(&motu->rx_packet_formats, motu->spec->flags, - data, V2_OPT_OUT_IFACE_MASK, V2_OPT_OUT_IFACE_SHIFT); - memcpy(motu->tx_packet_formats.pcm_chunks, motu->spec->tx_fixed_pcm_chunks, sizeof(motu->tx_packet_formats.pcm_chunks)); @@ -365,62 +275,35 @@ int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) const struct snd_motu_spec snd_motu_spec_828mk2 = { .name = "828mk2", .protocol_version = SND_MOTU_PROTOCOL_V2, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_RX_SEPARATED_MAIN | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | + .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, .tx_fixed_pcm_chunks = {14, 14, 0}, .rx_fixed_pcm_chunks = {14, 14, 0}, - .analog_in_ports = 8, - .analog_out_ports = 8, }; const struct snd_motu_spec snd_motu_spec_traveler = { .name = "Traveler", .protocol_version = SND_MOTU_PROTOCOL_V2, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_HAS_AESEBU_IFACE | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | + .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, .tx_fixed_pcm_chunks = {14, 14, 8}, .rx_fixed_pcm_chunks = {14, 14, 8}, - .analog_in_ports = 8, - .analog_out_ports = 8, }; const struct snd_motu_spec snd_motu_spec_ultralite = { .name = "UltraLite", .protocol_version = SND_MOTU_PROTOCOL_V2, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | // padding. - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | - SND_MOTU_SPEC_TX_MIDI_2ND_Q | - SND_MOTU_SPEC_RX_SEPARATED_MAIN, + .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q | + SND_MOTU_SPEC_TX_MIDI_2ND_Q, .tx_fixed_pcm_chunks = {14, 14, 0}, .rx_fixed_pcm_chunks = {14, 14, 0}, - .analog_in_ports = 8, - .analog_out_ports = 8, }; const struct snd_motu_spec snd_motu_spec_8pre = { .name = "8pre", .protocol_version = SND_MOTU_PROTOCOL_V2, - // In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for - // dummy 1/2. - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | - SND_MOTU_SPEC_HAS_OPT_IFACE_B | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | + .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, .tx_fixed_pcm_chunks = {10, 6, 0}, .rx_fixed_pcm_chunks = {10, 6, 0}, - .analog_in_ports = 8, - .analog_out_ports = 2, }; diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 903a7eb209f9..cc100d7be0bf 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -158,124 +158,6 @@ int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu, sizeof(reg)); } -static void calculate_fixed_part(struct snd_motu_packet_format *formats, - enum amdtp_stream_direction dir, - enum snd_motu_spec_flags flags, - unsigned char analog_ports) -{ - unsigned char pcm_chunks[3] = {0, 0, 0}; - - pcm_chunks[0] = analog_ports; - pcm_chunks[1] = analog_ports; - if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) - pcm_chunks[2] = analog_ports; - - if (dir == AMDTP_IN_STREAM) { - if (flags & SND_MOTU_SPEC_TX_MICINST_CHUNK) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) - pcm_chunks[2] += 2; - } - - if (flags & SND_MOTU_SPEC_TX_RETURN_CHUNK) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) - pcm_chunks[2] += 2; - } - - if (flags & SND_MOTU_SPEC_TX_REVERB_CHUNK) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - } else { - if (flags & SND_MOTU_SPEC_RX_SEPARATED_MAIN) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - - // Packets to v3 units include 2 chunks for phone 1/2, except - // for 176.4/192.0 kHz. - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - - if (flags & SND_MOTU_SPEC_HAS_AESEBU_IFACE) { - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - } - - /* - * At least, packets have two data chunks for S/PDIF on coaxial - * interface. - */ - pcm_chunks[0] += 2; - pcm_chunks[1] += 2; - - /* - * Fixed part consists of PCM chunks multiple of 4, with msg chunks. As - * a result, this part can includes empty data chunks. - */ - formats->fixed_part_pcm_chunks[0] = round_up(2 + pcm_chunks[0], 4) - 2; - formats->fixed_part_pcm_chunks[1] = round_up(2 + pcm_chunks[1], 4) - 2; - if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) - formats->fixed_part_pcm_chunks[2] = - round_up(2 + pcm_chunks[2], 4) - 2; -} - -static void calculate_differed_part(struct snd_motu_packet_format *formats, - enum snd_motu_spec_flags flags, u32 data, - u32 a_enable_mask, u32 a_no_adat_mask, - u32 b_enable_mask, u32 b_no_adat_mask) -{ - unsigned char pcm_chunks[3] = {0, 0, 0}; - int i; - - if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) && (data & a_enable_mask)) { - if (data & a_no_adat_mask) { - /* - * Additional two data chunks for S/PDIF on optical - * interface A. This includes empty data chunks. - */ - pcm_chunks[0] += 4; - pcm_chunks[1] += 4; - } else { - /* - * Additional data chunks for ADAT on optical interface - * A. - */ - pcm_chunks[0] += 8; - pcm_chunks[1] += 4; - } - } - - if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_B) && (data & b_enable_mask)) { - if (data & b_no_adat_mask) { - /* - * Additional two data chunks for S/PDIF on optical - * interface B. This includes empty data chunks. - */ - pcm_chunks[0] += 4; - pcm_chunks[1] += 4; - } else { - /* - * Additional data chunks for ADAT on optical interface - * B. - */ - pcm_chunks[0] += 8; - pcm_chunks[1] += 4; - } - } - - for (i = 0; i < 3; ++i) { - if (pcm_chunks[i] > 0) - pcm_chunks[i] = round_up(pcm_chunks[i], 4); - - formats->differed_part_pcm_chunks[i] = pcm_chunks[i]; - } -} - static int detect_packet_formats_828mk3(struct snd_motu *motu, u32 data) { if (data & V3_ENABLE_OPT_IN_IFACE_A) { @@ -339,20 +221,6 @@ int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) return err; data = be32_to_cpu(reg); - calculate_fixed_part(&motu->tx_packet_formats, AMDTP_IN_STREAM, - motu->spec->flags, motu->spec->analog_in_ports); - calculate_differed_part(&motu->tx_packet_formats, - motu->spec->flags, data, - V3_ENABLE_OPT_IN_IFACE_A, V3_NO_ADAT_OPT_IN_IFACE_A, - V3_ENABLE_OPT_IN_IFACE_B, V3_NO_ADAT_OPT_IN_IFACE_B); - - calculate_fixed_part(&motu->rx_packet_formats, AMDTP_OUT_STREAM, - motu->spec->flags, motu->spec->analog_out_ports); - calculate_differed_part(&motu->rx_packet_formats, - motu->spec->flags, data, - V3_ENABLE_OPT_OUT_IFACE_A, V3_NO_ADAT_OPT_OUT_IFACE_A, - V3_ENABLE_OPT_OUT_IFACE_B, V3_NO_ADAT_OPT_OUT_IFACE_B); - memcpy(motu->tx_packet_formats.pcm_chunks, motu->spec->tx_fixed_pcm_chunks, sizeof(motu->tx_packet_formats.pcm_chunks)); @@ -370,46 +238,24 @@ int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) const struct snd_motu_spec snd_motu_spec_828mk3 = { .name = "828mk3", .protocol_version = SND_MOTU_PROTOCOL_V3, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_TX_REVERB_CHUNK | - SND_MOTU_SPEC_RX_SEPARATED_MAIN | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | - SND_MOTU_SPEC_HAS_OPT_IFACE_B | - SND_MOTU_SPEC_RX_MIDI_3RD_Q | + .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | SND_MOTU_SPEC_TX_MIDI_3RD_Q, .tx_fixed_pcm_chunks = {18, 18, 14}, .rx_fixed_pcm_chunks = {14, 14, 10}, - .analog_in_ports = 8, - .analog_out_ports = 8, }; const struct snd_motu_spec snd_motu_spec_audio_express = { .name = "AudioExpress", .protocol_version = SND_MOTU_PROTOCOL_V3, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_RX_SEPARATED_MAIN | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | + .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_3RD_Q, .tx_fixed_pcm_chunks = {10, 10, 0}, .rx_fixed_pcm_chunks = {10, 10, 0}, - .analog_in_ports = 2, - .analog_out_ports = 4, }; const struct snd_motu_spec snd_motu_spec_4pre = { .name = "4pre", .protocol_version = SND_MOTU_PROTOCOL_V3, - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | - SND_MOTU_SPEC_TX_MICINST_CHUNK | - SND_MOTU_SPEC_TX_RETURN_CHUNK | - SND_MOTU_SPEC_RX_SEPARATED_MAIN, .tx_fixed_pcm_chunks = {10, 10, 0}, .rx_fixed_pcm_chunks = {10, 10, 0}, - .analog_in_ports = 2, - .analog_out_ports = 2, }; diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index d071b2342f11..e7948bf1f553 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -37,8 +37,6 @@ struct snd_motu_packet_format { unsigned char msg_chunks; unsigned char pcm_chunks[3]; - unsigned char fixed_part_pcm_chunks[3]; - unsigned char differed_part_pcm_chunks[3]; }; struct snd_motu { @@ -75,19 +73,10 @@ struct snd_motu { }; enum snd_motu_spec_flags { - SND_MOTU_SPEC_SUPPORT_CLOCK_X2 = 0x0001, - SND_MOTU_SPEC_SUPPORT_CLOCK_X4 = 0x0002, - SND_MOTU_SPEC_TX_MICINST_CHUNK = 0x0004, - SND_MOTU_SPEC_TX_RETURN_CHUNK = 0x0008, - SND_MOTU_SPEC_TX_REVERB_CHUNK = 0x0010, - SND_MOTU_SPEC_HAS_AESEBU_IFACE = 0x0020, - SND_MOTU_SPEC_HAS_OPT_IFACE_A = 0x0040, - SND_MOTU_SPEC_HAS_OPT_IFACE_B = 0x0080, - SND_MOTU_SPEC_RX_MIDI_2ND_Q = 0x0100, - SND_MOTU_SPEC_RX_MIDI_3RD_Q = 0x0200, - SND_MOTU_SPEC_TX_MIDI_2ND_Q = 0x0400, - SND_MOTU_SPEC_TX_MIDI_3RD_Q = 0x0800, - SND_MOTU_SPEC_RX_SEPARATED_MAIN = 0x1000, + SND_MOTU_SPEC_RX_MIDI_2ND_Q = 0x0001, + SND_MOTU_SPEC_RX_MIDI_3RD_Q = 0x0002, + SND_MOTU_SPEC_TX_MIDI_2ND_Q = 0x0004, + SND_MOTU_SPEC_TX_MIDI_3RD_Q = 0x0008, }; #define SND_MOTU_CLOCK_RATE_COUNT 6 @@ -121,9 +110,6 @@ struct snd_motu_spec { unsigned char tx_fixed_pcm_chunks[3]; unsigned char rx_fixed_pcm_chunks[3]; - - unsigned char analog_in_ports; - unsigned char analog_out_ports; }; extern const struct snd_motu_spec snd_motu_spec_828mk2; From 2b8f050e4ea97bd9851d023935e0ca5229e6905b Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:39 +0900 Subject: [PATCH 343/428] ALSA: firewire-motu: refactoring protocol v2 for clock source getter This commit splits the method to get clock source for protocol version 2 so that model-dependent operations are explicitly defined. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-13-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 48 +++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 1bdc905e8e22..2e6c3cc8a9e1 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -78,14 +78,10 @@ int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu, sizeof(reg)); } -static int get_clock_source(struct snd_motu *motu, u32 data, - enum snd_motu_clock_source *src) +static int detect_clock_source_optical_model(struct snd_motu *motu, u32 data, + enum snd_motu_clock_source *src) { - unsigned int index = data & V2_CLOCK_SRC_MASK; - if (index > 5) - return -EIO; - - switch (index) { + switch (data) { case 0: *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; break; @@ -118,12 +114,48 @@ static int get_clock_source(struct snd_motu *motu, u32 data, *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB; break; default: - return -EIO; + *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; + break; } return 0; } +static int v2_detect_clock_source(struct snd_motu *motu, u32 data, + enum snd_motu_clock_source *src) +{ + switch (data) { + case 0: + *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; + break; + case 2: + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; + break; + case 3: + *src = SND_MOTU_CLOCK_SOURCE_SPH; + break; + case 4: + *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; + break; + default: + *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; + break; + } + + return 0; +} + +static int get_clock_source(struct snd_motu *motu, u32 data, + enum snd_motu_clock_source *src) +{ + data &= V2_CLOCK_SRC_MASK; + if (motu->spec == &snd_motu_spec_828mk2 || + motu->spec == &snd_motu_spec_traveler) + return detect_clock_source_optical_model(motu, data, src); + else + return v2_detect_clock_source(motu, data, src); +} + int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu, enum snd_motu_clock_source *src) { From 7b47c0d719f47e990a4130534182058780f7322a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:40 +0900 Subject: [PATCH 344/428] ALSA: firewire-motu: refactoring protocol v3 for clock source getter This commit splits the method to get clock source for protocol version 3 so that model-dependent operations are explicitly defined. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-14-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v3.c | 114 +++++++++++++++++-------- 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index cc100d7be0bf..fd49d1fcf473 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -87,52 +87,98 @@ int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu, return 0; } +static int detect_clock_source_828mk3(struct snd_motu *motu, u32 data, + enum snd_motu_clock_source *src) +{ + switch (data) { + case 0x00: + *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; + break; + case 0x01: + *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; + break; + case 0x02: + *src = SND_MOTU_CLOCK_SOURCE_SPH; + break; + case 0x10: + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; + break; + case 0x18: + case 0x19: + { + __be32 reg; + u32 options; + int err; + + err = snd_motu_transaction_read(motu, + V3_OPT_IFACE_MODE_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + options = be32_to_cpu(reg); + + if (data == 0x18) { + if (options & V3_NO_ADAT_OPT_IN_IFACE_A) + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A; + else + *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A; + } else { + if (options & V3_NO_ADAT_OPT_IN_IFACE_B) + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B; + else + *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B; + } + + break; + } + default: + *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; + break; + } + + return 0; +} + +static int v3_detect_clock_source(struct snd_motu *motu, u32 data, + enum snd_motu_clock_source *src) +{ + switch (data) { + case 0x00: + *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; + break; + case 0x01: + *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; + break; + case 0x02: + *src = SND_MOTU_CLOCK_SOURCE_SPH; + break; + case 0x10: + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; + break; + default: + *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; + break; + } + + return 0; +} + int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu, enum snd_motu_clock_source *src) { __be32 reg; u32 data; - unsigned int val; int err; err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®, sizeof(reg)); if (err < 0) return err; - data = be32_to_cpu(reg); + data = be32_to_cpu(reg) & V3_CLOCK_SOURCE_MASK; - val = data & V3_CLOCK_SOURCE_MASK; - if (val == 0x00) { - *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; - } else if (val == 0x01) { - *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; - } else if (val == 0x02) { - *src = SND_MOTU_CLOCK_SOURCE_SPH; - } else if (val == 0x10) { - *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; - } else if (val == 0x18 || val == 0x19) { - err = snd_motu_transaction_read(motu, V3_OPT_IFACE_MODE_OFFSET, - ®, sizeof(reg)); - if (err < 0) - return err; - data = be32_to_cpu(reg); - - if (val == 0x18) { - if (data & V3_NO_ADAT_OPT_IN_IFACE_A) - *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A; - else - *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A; - } else { - if (data & V3_NO_ADAT_OPT_IN_IFACE_B) - *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B; - else - *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B; - } - } else { - *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; - } - - return 0; + if (motu->spec == &snd_motu_spec_828mk3) + return detect_clock_source_828mk3(motu, data, src); + else + return v3_detect_clock_source(motu, data, src); } int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu, From 506ad56a59086751eee28b6b6e5dff5572cd669f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 19 May 2020 20:16:41 +0900 Subject: [PATCH 345/428] ALSA: firewire-motu: refactoring protocol v2 for fetching mode switch This commit splits the method to switch fetching mode for protocol version 2 so that model-dependent operations are explicitly defined. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200519111641.123211-15-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 89 +++++++++++++++----------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 2e6c3cc8a9e1..e59e69ab1538 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -170,52 +170,69 @@ int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu, return get_clock_source(motu, be32_to_cpu(reg), src); } +// Expected for Traveler and 896HD, which implements Altera Cyclone EP1C3. +static int switch_fetching_mode_cyclone(struct snd_motu *motu, u32 *data, + bool enable) +{ + *data |= V2_CLOCK_MODEL_SPECIFIC; + + return 0; +} + +// For UltraLite and 8pre, which implements Xilinx Spartan XC3S200. +static int switch_fetching_mode_spartan(struct snd_motu *motu, u32 *data, + bool enable) +{ + unsigned int rate; + enum snd_motu_clock_source src; + int err; + + err = get_clock_source(motu, *data, &src); + if (err < 0) + return err; + + err = get_clock_rate(*data, &rate); + if (err < 0) + return err; + + if (src == SND_MOTU_CLOCK_SOURCE_SPH && rate > 48000) + *data |= V2_CLOCK_MODEL_SPECIFIC; + + return 0; +} + int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu, bool enable) { - enum snd_motu_clock_source src; - __be32 reg; - u32 data; - int err = 0; - - // 828mkII implements Altera ACEX 1K EP1K30. Nothing to do. - if (motu->spec == &snd_motu_spec_828mk2) + if (motu->spec == &snd_motu_spec_828mk2) { + // 828mkII implements Altera ACEX 1K EP1K30. Nothing to do. return 0; - - err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, ®, - sizeof(reg)); - if (err < 0) - return err; - data = be32_to_cpu(reg); - - err = get_clock_source(motu, data, &src); - if (err < 0) - return err; - - data &= ~(V2_CLOCK_FETCH_ENABLE | V2_CLOCK_MODEL_SPECIFIC); - if (enable) - data |= V2_CLOCK_FETCH_ENABLE; - - if (motu->spec == &snd_motu_spec_traveler) { - // Expected for Traveler and 896HD, which implements Altera - // Cyclone EP1C3. - data |= V2_CLOCK_MODEL_SPECIFIC; } else { - // For UltraLite and 8pre, which implements Xilinx Spartan - // XC3S200. - unsigned int rate; + __be32 reg; + u32 data; + int err; - err = get_clock_rate(data, &rate); + err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, + ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg); + + data &= ~(V2_CLOCK_FETCH_ENABLE | V2_CLOCK_MODEL_SPECIFIC); + if (enable) + data |= V2_CLOCK_FETCH_ENABLE; + + if (motu->spec == &snd_motu_spec_traveler) + err = switch_fetching_mode_cyclone(motu, &data, enable); + else + err = switch_fetching_mode_spartan(motu, &data, enable); if (err < 0) return err; - if (src == SND_MOTU_CLOCK_SOURCE_SPH && rate > 48000) - data |= V2_CLOCK_MODEL_SPECIFIC; + reg = cpu_to_be32(data); + return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, + ®, sizeof(reg)); } - - reg = cpu_to_be32(data); - return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, ®, - sizeof(reg)); } static int detect_packet_formats_828mk2(struct snd_motu *motu, u32 data) From 980b63f8d040a791e8d751b8065d12ad7865f976 Mon Sep 17 00:00:00 2001 From: Pavel Dobias Date: Fri, 22 May 2020 16:29:56 +0200 Subject: [PATCH 346/428] ASoC: max9867: add digital microphone controls MAX9867 codec has a possibility of connecting digital microphones. Add DAPM controls to be able to enable them. Signed-off-by: Pavel Dobias Link: https://lore.kernel.org/r/20200522142957.18364-2-dobias@2n.cz Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index f100070a59ca..93dd3d401f19 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -104,10 +104,24 @@ static const struct snd_kcontrol_new max9867_line_out_control = SOC_DAPM_DOUBLE_R("Switch", MAX9867_LEFTVOL, MAX9867_RIGHTVOL, 6, 1, 1); +/* DMIC mux */ +static const char *const dmic_mux_text[] = { + "ADC", "DMIC" +}; +static SOC_ENUM_SINGLE_DECL(left_dmic_mux_enum, + MAX9867_MICCONFIG, 5, dmic_mux_text); +static SOC_ENUM_SINGLE_DECL(right_dmic_mux_enum, + MAX9867_MICCONFIG, 4, dmic_mux_text); +static const struct snd_kcontrol_new max9867_left_dmic_mux = + SOC_DAPM_ENUM("DMICL Mux", left_dmic_mux_enum); +static const struct snd_kcontrol_new max9867_right_dmic_mux = + SOC_DAPM_ENUM("DMICR Mux", right_dmic_mux_enum); static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = { SND_SOC_DAPM_INPUT("MICL"), SND_SOC_DAPM_INPUT("MICR"), + SND_SOC_DAPM_INPUT("DMICL"), + SND_SOC_DAPM_INPUT("DMICR"), SND_SOC_DAPM_INPUT("LINL"), SND_SOC_DAPM_INPUT("LINR"), @@ -116,6 +130,10 @@ static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = { SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0, max9867_input_mixer_controls, ARRAY_SIZE(max9867_input_mixer_controls)), + SND_SOC_DAPM_MUX("DMICL Mux", SND_SOC_NOPM, 0, 0, + &max9867_left_dmic_mux), + SND_SOC_DAPM_MUX("DMICR Mux", SND_SOC_NOPM, 0, 0, + &max9867_right_dmic_mux), SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", MAX9867_PWRMAN, 1, 0), SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", MAX9867_PWRMAN, 0, 0), @@ -140,8 +158,12 @@ static const struct snd_soc_dapm_route max9867_audio_map[] = { {"Input Mixer", "Mic Capture Switch", "MICR"}, {"Input Mixer", "Line Capture Switch", "Left Line Input"}, {"Input Mixer", "Line Capture Switch", "Right Line Input"}, - {"ADCL", NULL, "Input Mixer"}, - {"ADCR", NULL, "Input Mixer"}, + {"DMICL Mux", "DMIC", "DMICL"}, + {"DMICR Mux", "DMIC", "DMICR"}, + {"DMICL Mux", "ADC", "Input Mixer"}, + {"DMICR Mux", "ADC", "Input Mixer"}, + {"ADCL", NULL, "DMICL Mux"}, + {"ADCR", NULL, "DMICR Mux"}, {"Digital", "Sidetone Switch", "ADCL"}, {"Digital", "Sidetone Switch", "ADCR"}, From 29c859df7b52080f0809b8a0b9d7b86fff379ef9 Mon Sep 17 00:00:00 2001 From: Pavel Dobias Date: Fri, 22 May 2020 16:29:57 +0200 Subject: [PATCH 347/428] ASoC: max9867: keep ADCs and DACs always on Updating power management register requires toggling the shutdown bit otherwise it causes unexpected behavior of the codec. However, toggling the shutdown bit results in loud speaker crackling. Setup the power management register only at startup to avoid that. Signed-off-by: Pavel Dobias Link: https://lore.kernel.org/r/20200522142957.18364-3-dobias@2n.cz Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 19 +++++++++---------- sound/soc/codecs/max9867.h | 1 - 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 93dd3d401f19..dc05c57db03a 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -125,8 +125,8 @@ static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = { SND_SOC_DAPM_INPUT("LINL"), SND_SOC_DAPM_INPUT("LINR"), - SND_SOC_DAPM_PGA("Left Line Input", MAX9867_PWRMAN, 6, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Line Input", MAX9867_PWRMAN, 5, 0, NULL, 0), + SND_SOC_DAPM_PGA("Left Line Input", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right Line Input", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0, max9867_input_mixer_controls, ARRAY_SIZE(max9867_input_mixer_controls)), @@ -134,8 +134,8 @@ static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = { &max9867_left_dmic_mux), SND_SOC_DAPM_MUX("DMICR Mux", SND_SOC_NOPM, 0, 0, &max9867_right_dmic_mux), - SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", MAX9867_PWRMAN, 1, 0), - SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", MAX9867_PWRMAN, 0, 0), + SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_MIXER("Digital", SND_SOC_NOPM, 0, 0, max9867_sidetone_mixer_controls, @@ -143,8 +143,8 @@ static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = { SND_SOC_DAPM_MIXER_NAMED_CTL("Output Mixer", SND_SOC_NOPM, 0, 0, max9867_output_mixer_controls, ARRAY_SIZE(max9867_output_mixer_controls)), - SND_SOC_DAPM_DAC("DACL", "HiFi Playback", MAX9867_PWRMAN, 3, 0), - SND_SOC_DAPM_DAC("DACR", "HiFi Playback", MAX9867_PWRMAN, 2, 0), + SND_SOC_DAPM_DAC("DACL", "HiFi Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DACR", "HiFi Playback", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_SWITCH("Master Playback", SND_SOC_NOPM, 0, 0, &max9867_line_out_control), SND_SOC_DAPM_OUTPUT("LOUT"), @@ -452,15 +452,14 @@ static int max9867_set_bias_level(struct snd_soc_component *component, if (err) return err; - err = regmap_update_bits(max9867->regmap, MAX9867_PWRMAN, - MAX9867_SHTDOWN, MAX9867_SHTDOWN); + err = regmap_write(max9867->regmap, + MAX9867_PWRMAN, 0xff); if (err) return err; } break; case SND_SOC_BIAS_OFF: - err = regmap_update_bits(max9867->regmap, MAX9867_PWRMAN, - MAX9867_SHTDOWN, 0); + err = regmap_write(max9867->regmap, MAX9867_PWRMAN, 0); if (err) return err; diff --git a/sound/soc/codecs/max9867.h b/sound/soc/codecs/max9867.h index d459d49449cb..3092c3b99075 100644 --- a/sound/soc/codecs/max9867.h +++ b/sound/soc/codecs/max9867.h @@ -58,7 +58,6 @@ #define MAX9867_MICCONFIG 0x15 #define MAX9867_MODECONFIG 0x16 #define MAX9867_PWRMAN 0x17 -#define MAX9867_SHTDOWN 0x80 #define MAX9867_REVISION 0xff #define MAX9867_CACHEREGNUM 10 From e0b2db351bc708037571deb3fc82c7d9043b4ea8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 23 May 2020 16:17:33 +0900 Subject: [PATCH 348/428] ALSA: firewire-motu: add support for MOTU UltraLite-mk3 (FireWire only model) UltraLite-mk3 was shipped 2008 by MOTU. This model has two lineups; FireWire-only and FireWire/USB2.0 Hybrid model. Additionally, the latter has two variants in respect of the type of IEEE 1394 connector; alpha and beta connector. This commit adds support for the FireWire-only model, which is already discontinued. $ python3 crpp < /sys/bus/firewire/devices/fw1/config_rom ROM header and bus information block ----------------------------------------------------------------- 400 0410353a bus_info_length 4, crc_length 16, crc 13626 404 31333934 bus_name "1394" 408 20ff7000 irmc 0, cmc 0, isc 1, bmc 0, cyc_clk_acc 255, max_rec 7 (256) 40c 0001f200 company_id 0001f2 | 410 000902c7 device_id 00000902c7 | EUI-64 0001f200000902c7 root directory ----------------------------------------------------------------- 414 0004ef04 directory_length 4, crc 61188 418 030001f2 vendor 41c 0c0083c0 node capabilities per IEEE 1394 420 d1000002 --> unit directory at 428 424 8d000005 --> eui-64 leaf at 438 unit directory at 428 ----------------------------------------------------------------- 428 00035556 directory_length 3, crc 21846 42c 120001f2 specifier id 430 13000019 version 434 17100800 model eui-64 leaf at 438 ----------------------------------------------------------------- 438 0002f3c5 leaf_length 2, crc 62405 43c 0001f200 company_id 0001f2 | 440 000902c7 device_id 00000902c7 | EUI-64 0001f200000902c7 Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200523071733.170129-1-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v3.c | 9 +++++++++ sound/firewire/motu/motu.c | 1 + sound/firewire/motu/motu.h | 1 + 3 files changed, 11 insertions(+) diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index fd49d1fcf473..01a47ac7bb2d 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -290,6 +290,15 @@ const struct snd_motu_spec snd_motu_spec_828mk3 = { .rx_fixed_pcm_chunks = {14, 14, 10}, }; +const struct snd_motu_spec snd_motu_spec_ultralite_mk3 = { + .name = "UltraLiteMk3", + .protocol_version = SND_MOTU_PROTOCOL_V3, + .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | + SND_MOTU_SPEC_TX_MIDI_3RD_Q, + .tx_fixed_pcm_chunks = {18, 14, 10}, + .rx_fixed_pcm_chunks = {14, 14, 14}, +}; + const struct snd_motu_spec snd_motu_spec_audio_express = { .name = "AudioExpress", .protocol_version = SND_MOTU_PROTOCOL_V3, diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index e5b6f634aa35..a4929c1302dc 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c @@ -189,6 +189,7 @@ static const struct ieee1394_device_id motu_id_table[] = { SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite), SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre), SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3), // FireWire only. + SND_MOTU_DEV_ENTRY(0x000019, &snd_motu_spec_ultralite_mk3), // FireWire only. SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3), // Hybrid. SND_MOTU_DEV_ENTRY(0x000033, &snd_motu_spec_audio_express), SND_MOTU_DEV_ENTRY(0x000045, &snd_motu_spec_4pre), diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index e7948bf1f553..3d0236ee6716 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -118,6 +118,7 @@ extern const struct snd_motu_spec snd_motu_spec_ultralite; extern const struct snd_motu_spec snd_motu_spec_8pre; extern const struct snd_motu_spec snd_motu_spec_828mk3; +extern const struct snd_motu_spec snd_motu_spec_ultralite_mk3; extern const struct snd_motu_spec snd_motu_spec_audio_express; extern const struct snd_motu_spec snd_motu_spec_4pre; From 02e756363fc936917bed7320199c80729b2a825c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:14 +0900 Subject: [PATCH 349/428] ASoC: add soc-link.c Current ALSA SoC has many dai_link->xxx() functions. But, it is implemented randomly at random place. This patch creats new soc-link.c and collect dai_link related operation into it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/871rn84ys5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 13 +++++++++++++ sound/soc/Makefile | 2 +- sound/soc/soc-core.c | 12 ++++-------- sound/soc/soc-link.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 include/sound/soc-link.h create mode 100644 sound/soc/soc-link.c diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h new file mode 100644 index 000000000000..7fc5cead5942 --- /dev/null +++ b/include/sound/soc-link.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * soc-link.h + * + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto + */ +#ifndef __SOC_LINK_H +#define __SOC_LINK_H + +int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); + +#endif /* __SOC_LINK_H */ diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 861a21b79484..70a5f19ea3a1 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o -snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o +snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e697258d2ffc..955e175643d7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #define CREATE_TRACE_POINTS @@ -1049,14 +1050,9 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, rtd->pmdown_time = pmdown_time; /* do machine specific initialization */ - if (dai_link->init) { - ret = dai_link->init(rtd); - if (ret < 0) { - dev_err(card->dev, "ASoC: failed to init %s: %d\n", - dai_link->name, ret); - return ret; - } - } + ret = snd_soc_link_init(rtd); + if (ret < 0) + return ret; if (dai_link->dai_fmt) { ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c new file mode 100644 index 000000000000..bba6f35af0ad --- /dev/null +++ b/sound/soc/soc-link.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// soc-link.c +// +// Copyright (C) 2019 Renesas Electronics Corp. +// Kuninori Morimoto +// +#include +#include + +#define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret) +static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd, + const char *func, int ret) +{ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + case 0: + break; + default: + dev_err(rtd->dev, + "ASoC: error at %s on %s: %d\n", + func, rtd->dai_link->name, ret); + } + + return ret; +} + +int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret = 0; + + if (rtd->dai_link->init) + ret = rtd->dai_link->init(rtd); + + return soc_link_ret(rtd, ret); +} From a5e6c1090001b8a14e797364dde7c84236465fc7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:19 +0900 Subject: [PATCH 350/428] ASoC: soc-link: move soc_rtd_xxx() dai_link related function should be implemented at soc-link.c. This patch moves soc-pcm soc_rtd_xxx() to soc-link as snd_soc_link_xxx() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87zh9w3k7k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 13 ++++++ sound/soc/soc-link.c | 65 +++++++++++++++++++++++++++++ sound/soc/soc-pcm.c | 88 ++++++---------------------------------- 3 files changed, 91 insertions(+), 75 deletions(-) diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 7fc5cead5942..689aa93be78e 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -9,5 +9,18 @@ #define __SOC_LINK_H int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); +int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); +void snd_soc_link_shutdown(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); +int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); +int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +void snd_soc_link_hw_free(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); +int snd_soc_link_trigger(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream, int cmd); #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index bba6f35af0ad..3cb5d1f52e85 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -35,3 +35,68 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) return soc_link_ret(rtd, ret); } + +int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + int ret = 0; + + if (rtd->dai_link->ops && + rtd->dai_link->ops->startup) + ret = rtd->dai_link->ops->startup(substream); + + return soc_link_ret(rtd, ret); +} + +void snd_soc_link_shutdown(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + if (rtd->dai_link->ops && + rtd->dai_link->ops->shutdown) + rtd->dai_link->ops->shutdown(substream); +} + +int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + int ret = 0; + + if (rtd->dai_link->ops && + rtd->dai_link->ops->prepare) + ret = rtd->dai_link->ops->prepare(substream); + + return soc_link_ret(rtd, ret); +} + +int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int ret = 0; + + if (rtd->dai_link->ops && + rtd->dai_link->ops->hw_params) + ret = rtd->dai_link->ops->hw_params(substream, params); + + return soc_link_ret(rtd, ret); +} + +void snd_soc_link_hw_free(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + if (rtd->dai_link->ops && + rtd->dai_link->ops->hw_free) + rtd->dai_link->ops->hw_free(substream); +} + +int snd_soc_link_trigger(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream, int cmd) +{ + int ret = 0; + + if (rtd->dai_link->ops && + rtd->dai_link->ops->trigger) + ret = rtd->dai_link->ops->trigger(substream, cmd); + + return soc_link_ret(rtd, ret); +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b7899da4217e..b443950835ca 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #define DPCM_MAX_BE_USERS 8 @@ -202,60 +203,6 @@ static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm) } #endif -static int soc_rtd_startup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->startup) - return rtd->dai_link->ops->startup(substream); - return 0; -} - -static void soc_rtd_shutdown(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->shutdown) - rtd->dai_link->ops->shutdown(substream); -} - -static int soc_rtd_prepare(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->prepare) - return rtd->dai_link->ops->prepare(substream); - return 0; -} - -static int soc_rtd_hw_params(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->hw_params) - return rtd->dai_link->ops->hw_params(substream, params); - return 0; -} - -static void soc_rtd_hw_free(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->hw_free) - rtd->dai_link->ops->hw_free(substream); -} - -static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, - int cmd) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->trigger) - return rtd->dai_link->ops->trigger(substream, cmd); - return 0; -} - /** * snd_soc_runtime_action() - Increment/Decrement active count for * PCM runtime components @@ -736,7 +683,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) for_each_rtd_dais(rtd, i, dai) snd_soc_dai_shutdown(dai, substream); - soc_rtd_shutdown(rtd, substream); + snd_soc_link_shutdown(rtd, substream); soc_pcm_components_close(substream); @@ -783,12 +730,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) goto component_err; - ret = soc_rtd_startup(rtd, substream); - if (ret < 0) { - pr_err("ASoC: %s startup failed: %d\n", - rtd->dai_link->name, ret); + ret = snd_soc_link_startup(rtd, substream); + if (ret < 0) goto rtd_startup_err; - } /* startup the audio subsystem */ for_each_rtd_dais(rtd, i, dai) { @@ -870,7 +814,7 @@ config_err: for_each_rtd_dais(rtd, i, dai) snd_soc_dai_shutdown(dai, substream); - soc_rtd_shutdown(rtd, substream); + snd_soc_link_shutdown(rtd, substream); rtd_startup_err: soc_pcm_components_close(substream); component_err: @@ -912,12 +856,9 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - ret = soc_rtd_prepare(rtd, substream); - if (ret < 0) { - dev_err(rtd->card->dev, - "ASoC: machine prepare error: %d\n", ret); + ret = snd_soc_link_prepare(rtd, substream); + if (ret < 0) goto out; - } for_each_rtd_components(rtd, i, component) { ret = snd_soc_component_prepare(component, substream); @@ -1002,12 +943,9 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, if (ret) goto out; - ret = soc_rtd_hw_params(rtd, substream, params); - if (ret < 0) { - dev_err(rtd->card->dev, - "ASoC: machine hw_params failed: %d\n", ret); + ret = snd_soc_link_hw_params(rtd, substream, params); + if (ret < 0) goto out; - } for_each_rtd_codec_dais(rtd, i, codec_dai) { struct snd_pcm_hw_params codec_params; @@ -1117,7 +1055,7 @@ codec_err: codec_dai->rate = 0; } - soc_rtd_hw_free(rtd, substream); + snd_soc_link_hw_free(rtd, substream); mutex_unlock(&rtd->card->pcm_mutex); return ret; @@ -1149,7 +1087,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) } /* free any machine hw params */ - soc_rtd_hw_free(rtd, substream); + snd_soc_link_hw_free(rtd, substream); /* free any component resources */ soc_pcm_components_hw_free(substream, NULL); @@ -1172,7 +1110,7 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) struct snd_soc_component *component; int i, ret; - ret = soc_rtd_trigger(rtd, substream, cmd); + ret = snd_soc_link_trigger(rtd, substream, cmd); if (ret < 0) return ret; @@ -1201,7 +1139,7 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) return ret; } - ret = soc_rtd_trigger(rtd, substream, cmd); + ret = snd_soc_link_trigger(rtd, substream, cmd); if (ret < 0) return ret; From 7cf3c5b4a04f4b27d964089630290beccc115f9f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:31 +0900 Subject: [PATCH 351/428] ASoC: soc-link: remove unneeded parameter from snd_soc_link_xxx() "rtd" can be created from "substream". Let's cleanup snd_soc_link_xxx(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87y2pg3k78.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 18 ++++++------------ sound/soc/soc-link.c | 26 ++++++++++++++------------ sound/soc/soc-pcm.c | 18 +++++++++--------- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 689aa93be78e..2a81dca945cd 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -9,18 +9,12 @@ #define __SOC_LINK_H int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); -int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream); -void snd_soc_link_shutdown(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream); -int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream); -int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, +int snd_soc_link_startup(struct snd_pcm_substream *substream); +void snd_soc_link_shutdown(struct snd_pcm_substream *substream); +int snd_soc_link_prepare(struct snd_pcm_substream *substream); +int snd_soc_link_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); -void snd_soc_link_hw_free(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream); -int snd_soc_link_trigger(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, int cmd); +void snd_soc_link_hw_free(struct snd_pcm_substream *substream); +int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd); #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 3cb5d1f52e85..5ce3e209b1a8 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -36,9 +36,9 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) return soc_link_ret(rtd, ret); } -int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) +int snd_soc_link_startup(struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; if (rtd->dai_link->ops && @@ -48,17 +48,18 @@ int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, return soc_link_ret(rtd, ret); } -void snd_soc_link_shutdown(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) +void snd_soc_link_shutdown(struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) rtd->dai_link->ops->shutdown(substream); } -int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) +int snd_soc_link_prepare(struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; if (rtd->dai_link->ops && @@ -68,10 +69,10 @@ int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, return soc_link_ret(rtd, ret); } -int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, +int snd_soc_link_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; if (rtd->dai_link->ops && @@ -81,17 +82,18 @@ int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, return soc_link_ret(rtd, ret); } -void snd_soc_link_hw_free(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) +void snd_soc_link_hw_free(struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) rtd->dai_link->ops->hw_free(substream); } -int snd_soc_link_trigger(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, int cmd) +int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; if (rtd->dai_link->ops && diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b443950835ca..0204a3ecfc8b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -683,7 +683,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) for_each_rtd_dais(rtd, i, dai) snd_soc_dai_shutdown(dai, substream); - snd_soc_link_shutdown(rtd, substream); + snd_soc_link_shutdown(substream); soc_pcm_components_close(substream); @@ -730,7 +730,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) goto component_err; - ret = snd_soc_link_startup(rtd, substream); + ret = snd_soc_link_startup(substream); if (ret < 0) goto rtd_startup_err; @@ -814,7 +814,7 @@ config_err: for_each_rtd_dais(rtd, i, dai) snd_soc_dai_shutdown(dai, substream); - snd_soc_link_shutdown(rtd, substream); + snd_soc_link_shutdown(substream); rtd_startup_err: soc_pcm_components_close(substream); component_err: @@ -856,7 +856,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - ret = snd_soc_link_prepare(rtd, substream); + ret = snd_soc_link_prepare(substream); if (ret < 0) goto out; @@ -943,7 +943,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, if (ret) goto out; - ret = snd_soc_link_hw_params(rtd, substream, params); + ret = snd_soc_link_hw_params(substream, params); if (ret < 0) goto out; @@ -1055,7 +1055,7 @@ codec_err: codec_dai->rate = 0; } - snd_soc_link_hw_free(rtd, substream); + snd_soc_link_hw_free(substream); mutex_unlock(&rtd->card->pcm_mutex); return ret; @@ -1087,7 +1087,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) } /* free any machine hw params */ - snd_soc_link_hw_free(rtd, substream); + snd_soc_link_hw_free(substream); /* free any component resources */ soc_pcm_components_hw_free(substream, NULL); @@ -1110,7 +1110,7 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) struct snd_soc_component *component; int i, ret; - ret = snd_soc_link_trigger(rtd, substream, cmd); + ret = snd_soc_link_trigger(substream, cmd); if (ret < 0) return ret; @@ -1139,7 +1139,7 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) return ret; } - ret = snd_soc_link_trigger(rtd, substream, cmd); + ret = snd_soc_link_trigger(substream, cmd); if (ret < 0) return ret; From 0cbbf8a0399518e5b865f9a1320d704c1d621703 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:36 +0900 Subject: [PATCH 352/428] ASoC: soc-link: add snd_soc_link_be_hw_params_fixup() dai_link related function should be implemented at soc-link.c. This patch adds snd_soc_link_be_hw_params_fixup(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87wo503k73.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 3 +++ sound/soc/soc-core.c | 6 +++++- sound/soc/soc-dai.c | 9 ++++----- sound/soc/soc-link.c | 11 +++++++++++ sound/soc/soc-pcm.c | 13 +++---------- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 2a81dca945cd..aae72f668de6 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -9,6 +9,9 @@ #define __SOC_LINK_H int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); +int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); + int snd_soc_link_startup(struct snd_pcm_substream *substream); void snd_soc_link_shutdown(struct snd_pcm_substream *substream); int snd_soc_link_prepare(struct snd_pcm_substream *substream); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 955e175643d7..e1b65059c0c4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1656,7 +1656,11 @@ match: dai_link->dpcm_playback = 1; dai_link->dpcm_capture = 1; - /* override any BE fixups */ + /* + * override any BE fixups + * see + * snd_soc_link_be_hw_params_fixup() + */ dai_link->be_hw_params_fixup = component->driver->be_hw_params_fixup; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index ce4e1fd1ab79..2c6ac3b0afa5 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -8,6 +8,7 @@ #include #include +#include #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret) static inline int _soc_dai_ret(struct snd_soc_dai *dai, @@ -313,11 +314,9 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, int ret = 0; /* perform any topology hw_params fixups before DAI */ - if (rtd->dai_link->be_hw_params_fixup) { - ret = rtd->dai_link->be_hw_params_fixup(rtd, params); - if (ret < 0) - goto end; - } + ret = snd_soc_link_be_hw_params_fixup(rtd, params); + if (ret < 0) + goto end; if (dai->driver->ops && dai->driver->ops->hw_params) diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 5ce3e209b1a8..113a4d1b2262 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -36,6 +36,17 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) return soc_link_ret(rtd, ret); } +int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + int ret = 0; + + if (rtd->dai_link->be_hw_params_fixup) + ret = rtd->dai_link->be_hw_params_fixup(rtd, params); + + return soc_link_ret(rtd, ret); +} + int snd_soc_link_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 0204a3ecfc8b..80dd3cf6200c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2079,16 +2079,9 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) sizeof(struct snd_pcm_hw_params)); /* perform any hw_params fixups */ - if (be->dai_link->be_hw_params_fixup) { - ret = be->dai_link->be_hw_params_fixup(be, - &dpcm->hw_params); - if (ret < 0) { - dev_err(be->dev, - "ASoC: hw_params BE fixup failed %d\n", - ret); - goto unwind; - } - } + ret = snd_soc_link_be_hw_params_fixup(be, &dpcm->hw_params); + if (ret < 0) + goto unwind; /* copy the fixed-up hw params for BE dai */ memcpy(&be->dpcm[stream].hw_params, &dpcm->hw_params, From 9ab711cb84d4b77fb3929fabc5e3756d5010af14 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:41 +0900 Subject: [PATCH 353/428] ASoC: soc-link: add snd_soc_link_compr_startup() dai_link related function should be implemented at soc-link.c. This patch adds snd_soc_link_compr_startup(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87v9kk3k6y.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 2 ++ sound/soc/soc-compress.c | 24 +++++++----------------- sound/soc/soc-link.c | 13 +++++++++++++ 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index aae72f668de6..20fe46f31e33 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -20,4 +20,6 @@ int snd_soc_link_hw_params(struct snd_pcm_substream *substream, void snd_soc_link_hw_free(struct snd_pcm_substream *substream); int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd); +int snd_soc_link_compr_startup(struct snd_compr_stream *cstream); + #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 62ece729e425..ddc6c6f69d2f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static int soc_compr_components_open(struct snd_compr_stream *cstream, @@ -95,15 +96,9 @@ static int soc_compr_open(struct snd_compr_stream *cstream) if (ret < 0) goto machine_err; - if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) { - ret = rtd->dai_link->compr_ops->startup(cstream); - if (ret < 0) { - dev_err(rtd->dev, - "Compress ASoC: %s startup failed: %d\n", - rtd->dai_link->name, ret); - goto machine_err; - } - } + ret = snd_soc_link_compr_startup(cstream); + if (ret < 0) + goto machine_err; snd_soc_runtime_activate(rtd, cstream->direction); @@ -179,14 +174,9 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) if (ret < 0) goto open_err; - if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) { - ret = fe->dai_link->compr_ops->startup(cstream); - if (ret < 0) { - pr_err("Compress ASoC: %s startup failed: %d\n", - fe->dai_link->name, ret); - goto machine_err; - } - } + ret = snd_soc_link_compr_startup(cstream); + if (ret < 0) + goto machine_err; dpcm_clear_pending_state(fe, stream); dpcm_path_put(&list); diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 113a4d1b2262..7f0fb53c435a 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -113,3 +113,16 @@ int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd) return soc_link_ret(rtd, ret); } + +int snd_soc_link_compr_startup(struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + int ret = 0; + + if (rtd->dai_link->compr_ops && + rtd->dai_link->compr_ops->startup) + ret = rtd->dai_link->compr_ops->startup(cstream); + + return soc_link_ret(rtd, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup); From 0e532c99b468d6e4fc4e1d29b45ffe2749db6d07 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:45 +0900 Subject: [PATCH 354/428] ASoC: soc-link: add snd_soc_link_compr_shutdown() dai_link related function should be implemented at soc-link.c. This patch adds snd_soc_link_compr_shutdown(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87tv043k6u.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 1 + sound/soc/soc-compress.c | 6 ++---- sound/soc/soc-link.c | 10 ++++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 20fe46f31e33..9ada62f8186f 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -21,5 +21,6 @@ void snd_soc_link_hw_free(struct snd_pcm_substream *substream); int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd); int snd_soc_link_compr_startup(struct snd_compr_stream *cstream); +void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream); #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index ddc6c6f69d2f..327bec052954 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -227,8 +227,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) if (!snd_soc_dai_active(codec_dai)) codec_dai->rate = 0; - if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) - rtd->dai_link->compr_ops->shutdown(cstream); + snd_soc_link_compr_shutdown(cstream); soc_compr_components_free(cstream, NULL); @@ -283,8 +282,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].runtime = NULL; - if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown) - fe->dai_link->compr_ops->shutdown(cstream); + snd_soc_link_compr_shutdown(cstream); soc_compr_components_free(cstream, NULL); diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 7f0fb53c435a..2cfe7f88b809 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -126,3 +126,13 @@ int snd_soc_link_compr_startup(struct snd_compr_stream *cstream) return soc_link_ret(rtd, ret); } EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup); + +void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + + if (rtd->dai_link->compr_ops && + rtd->dai_link->compr_ops->shutdown) + rtd->dai_link->compr_ops->shutdown(cstream); +} +EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown); From eab810f37ff5fd76172ac903e5e732d6b72fc834 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:50 +0900 Subject: [PATCH 355/428] ASoC: soc-link: add snd_soc_link_compr_set_params() dai_link related function should be implemented at soc-link.c. This patch adds snd_soc_link_compr_set_params(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87sgfo3k6q.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 1 + sound/soc/soc-compress.c | 16 ++++++---------- sound/soc/soc-link.c | 13 +++++++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 9ada62f8186f..3dd6e33e94ec 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -22,5 +22,6 @@ int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd); int snd_soc_link_compr_startup(struct snd_compr_stream *cstream); void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream); +int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream); #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 327bec052954..4984b6a2c370 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -439,11 +439,9 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, if (ret < 0) goto err; - if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { - ret = rtd->dai_link->compr_ops->set_params(cstream); - if (ret < 0) - goto err; - } + ret = snd_soc_link_compr_set_params(cstream); + if (ret < 0) + goto err; if (cstream->direction == SND_COMPRESS_PLAYBACK) snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, @@ -507,11 +505,9 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, if (ret < 0) goto out; - if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) { - ret = fe->dai_link->compr_ops->set_params(cstream); - if (ret < 0) - goto out; - } + ret = snd_soc_link_compr_set_params(cstream); + if (ret < 0) + goto out; dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 2cfe7f88b809..248e1be4e1eb 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -136,3 +136,16 @@ void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream) rtd->dai_link->compr_ops->shutdown(cstream); } EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown); + +int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + int ret = 0; + + if (rtd->dai_link->compr_ops && + rtd->dai_link->compr_ops->set_params) + ret = rtd->dai_link->compr_ops->set_params(cstream); + + return soc_link_ret(rtd, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params); From 523773b9ea9f430810332aa117ea48f8feafce9a Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:07 +0300 Subject: [PATCH 356/428] ASoC: SOF: loader: Adjust validation condition for fw_offset Condition in if statement should be same as trace message and FW size equal to zero (after skipping offset) should be marked as invalid. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 2 +- sound/soc/sof/loader.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index d762b3e1ce4a..441d05cda604 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -293,7 +293,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) chip_info = desc->chip_info; - if (plat_data->fw->size < plat_data->fw_offset) { + if (plat_data->fw->size <= plat_data->fw_offset) { dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n"); return -EINVAL; } diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 4a5b57ecf359..eed3d1e65685 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -385,7 +385,7 @@ static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw, struct snd_sof_fw_header *header; size_t fw_size = fw->size - fw_offset; - if (fw->size < fw_offset) { + if (fw->size <= fw_offset) { dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n"); return -EINVAL; } From a80cf1987a6e728b4d5c8e5041132d46e89c7a45 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:08 +0300 Subject: [PATCH 357/428] ASoC: SOF: Introduce extended manifest Extended manifest is a place to store build time known firmware metadata, for example firmware version or used compiler description. Given information is read on host side before firmware startup. This part of output binary is located as a first structure in binary file. Extended manifest should be skipped in firmware loading routine. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 65 ++++++++++++++++++ sound/soc/sof/loader.c | 112 +++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 include/sound/sof/ext_manifest.h diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h new file mode 100644 index 000000000000..5c1f03603919 --- /dev/null +++ b/include/sound/sof/ext_manifest.h @@ -0,0 +1,65 @@ +/* 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) 2020 Intel Corporation. All rights reserved. + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + */ + +#ifndef __SOF_FIRMWARE_EXT_MANIFEST_H__ +#define __SOF_FIRMWARE_EXT_MANIFEST_H__ + +#include +#include +#include + +/* In ASCII `XMan` */ +#define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 + +/* Build u32 number in format MMmmmppp */ +#define SOF_EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ((uint32_t)( \ + ((MAJOR) << 24) | \ + ((MINOR) << 12) | \ + (PATH))) + +/* check extended manifest version consistency */ +#define SOF_EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ + ((host_ver) & GENMASK(31, 24)) != \ + ((cli_ver) & GENMASK(31, 24))) + +/* used extended manifest header version */ +#define SOF_EXT_MAN_VERSION SOF_EXT_MAN_BUILD_VERSION(1, 0, 0) + +/* extended manifest header, deleting any field breaks backward compatibility */ +struct sof_ext_man_header { + uint32_t magic; /*< identification number, */ + /*< EXT_MAN_MAGIC_NUMBER */ + uint32_t full_size; /*< [bytes] full size of ext_man, */ + /*< (header + content + padding) */ + uint32_t header_size; /*< [bytes] makes header extensionable, */ + /*< after append new field to ext_man header */ + /*< then backward compatible won't be lost */ + uint32_t header_version; /*< value of EXT_MAN_VERSION */ + /*< not related with following content */ + + /* just after this header should be list of ext_man_elem_* elements */ +} __packed; + +/* Now define extended manifest elements */ + +/* extended manifest element header */ +struct sof_ext_man_elem_header { + uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ + uint32_t size; /*< in bytes, including header size */ + + /* just after this header should be type dependent content */ +} __packed; + +#endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index eed3d1e65685..a2c2dc17e9ab 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -12,6 +12,7 @@ #include #include +#include #include "ops.h" static int get_ext_windows(struct snd_sof_dev *sdev, @@ -126,6 +127,100 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +static ssize_t snd_sof_ext_man_size(const struct firmware *fw) +{ + const struct sof_ext_man_header *head; + + head = (struct sof_ext_man_header *)fw->data; + + /* + * assert fw size is big enough to contain extended manifest header, + * it prevents from reading unallocated memory from `head` in following + * step. + */ + if (fw->size < sizeof(*head)) + return -EINVAL; + + /* + * When fw points to extended manifest, + * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER. + */ + if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER) + return head->full_size; + + /* otherwise given fw don't have an extended manifest */ + return 0; +} + +/* parse extended FW manifest data structures */ +static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, + const struct firmware *fw) +{ + const struct sof_ext_man_elem_header *elem_hdr; + const struct sof_ext_man_header *head; + ssize_t ext_man_size; + ssize_t remaining; + uintptr_t iptr; + int ret = 0; + + head = (struct sof_ext_man_header *)fw->data; + remaining = head->full_size - head->header_size; + ext_man_size = snd_sof_ext_man_size(fw); + + /* Assert firmware starts with extended manifest */ + if (ext_man_size <= 0) + return ext_man_size; + + /* incompatible version */ + if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION, + head->header_version)) { + dev_err(sdev->dev, "error: extended manifest version 0x%X differ from used 0x%X\n", + head->header_version, SOF_EXT_MAN_VERSION); + return -EINVAL; + } + + /* get first extended manifest element header */ + iptr = (uintptr_t)fw->data + head->header_size; + + while (remaining > sizeof(*elem_hdr)) { + elem_hdr = (struct sof_ext_man_elem_header *)iptr; + + dev_dbg(sdev->dev, "found sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + + if (elem_hdr->size < sizeof(*elem_hdr) || + elem_hdr->size > remaining) { + dev_err(sdev->dev, "error: invalid sof_ext_man header size, type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + return -EINVAL; + } + + /* process structure data */ + switch (elem_hdr->type) { + default: + dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + break; + } + + if (ret < 0) { + dev_err(sdev->dev, "error: failed to parse sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + return ret; + } + + remaining -= elem_hdr->size; + iptr += elem_hdr->size; + } + + if (remaining) { + dev_err(sdev->dev, "error: sof_ext_man header is inconsistent\n"); + return -EINVAL; + } + + return ext_man_size; +} + /* * IPC Firmware ready. */ @@ -473,6 +568,7 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; const char *fw_filename; + ssize_t ext_man_size; int ret; /* Don't request firmware again if firmware is already requested */ @@ -490,11 +586,27 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", fw_filename, ret); + goto err; } else { dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename); } + /* check for extended manifest */ + ext_man_size = snd_sof_fw_ext_man_parse(sdev, plat_data->fw); + if (ext_man_size > 0) { + /* when no error occurred, drop extended manifest */ + plat_data->fw_offset = ext_man_size; + } else if (!ext_man_size) { + /* No extended manifest, so nothing to skip during FW load */ + dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n"); + } else { + ret = ext_man_size; + dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", + fw_filename, ret); + } + +err: kfree(fw_filename); return ret; From 3e2a89d3ee052ef5346ba933e557c807333ced11 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:09 +0300 Subject: [PATCH 358/428] ASoC: SOF: ext_manifest: parse firmware version The firmware version can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-4-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 14 ++++++++++++++ sound/soc/sof/loader.c | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index 5c1f03603919..6ed787eb788c 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -19,6 +19,7 @@ #include #include #include +#include /* In ASCII `XMan` */ #define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 @@ -54,6 +55,11 @@ struct sof_ext_man_header { /* Now define extended manifest elements */ +/* Extended manifest elements types */ +enum sof_ext_man_elem_type { + SOF_EXT_MAN_ELEM_FW_VERSION = 0, +}; + /* extended manifest element header */ struct sof_ext_man_elem_header { uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ @@ -62,4 +68,12 @@ struct sof_ext_man_elem_header { /* just after this header should be type dependent content */ } __packed; +/* FW version */ +struct sof_ext_man_fw_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_fw_version version; + uint32_t flags; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index a2c2dc17e9ab..8b42613304a7 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -127,6 +127,19 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +static int ext_man_get_fw_version(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_fw_version *v = + container_of(hdr, struct sof_ext_man_fw_version, hdr); + + memcpy(&sdev->fw_ready.version, &v->version, sizeof(v->version)); + sdev->fw_ready.flags = v->flags; + + /* log ABI versions and check FW compatibility */ + return snd_sof_ipc_valid(sdev); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head; @@ -197,6 +210,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, /* process structure data */ switch (elem_hdr->type) { + case SOF_EXT_MAN_ELEM_FW_VERSION: + ret = ext_man_get_fw_version(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); From 8d809c15acf23bb2863ec08578ab72de860b3abc Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:10 +0300 Subject: [PATCH 359/428] ASoC: SOF: ext_manifest: parse windows The window description can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-5-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 8 ++++++++ sound/soc/sof/loader.c | 25 +++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index 6ed787eb788c..0001fc5779ef 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -58,6 +58,7 @@ struct sof_ext_man_header { /* Extended manifest elements types */ enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, + SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, }; /* extended manifest element header */ @@ -76,4 +77,11 @@ struct sof_ext_man_fw_version { uint32_t flags; } __packed; +/* extended data memory windows for IPC, trace and debug */ +struct sof_ext_man_window { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_window ipc_window; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 8b42613304a7..6e92a1285b91 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -20,13 +20,21 @@ static int get_ext_windows(struct snd_sof_dev *sdev, { const struct sof_ipc_window *w = container_of(ext_hdr, struct sof_ipc_window, ext_hdr); + size_t w_size = struct_size(w, window, w->num_windows); if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) return -EINVAL; + if (sdev->info_window) { + if (memcmp(sdev->info_window, w, w_size)) { + dev_err(sdev->dev, "error: mismatch between window descriptor from extended manifest and mailbox"); + return -EINVAL; + } + return 0; + } + /* keep a local copy of the data */ - sdev->info_window = kmemdup(w, struct_size(w, window, w->num_windows), - GFP_KERNEL); + sdev->info_window = kmemdup(w, w_size, GFP_KERNEL); if (!sdev->info_window) return -ENOMEM; @@ -140,6 +148,16 @@ static int ext_man_get_fw_version(struct snd_sof_dev *sdev, return snd_sof_ipc_valid(sdev); } +static int ext_man_get_windows(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_window *w; + + w = container_of(hdr, struct sof_ext_man_window, hdr); + + return get_ext_windows(sdev, &w->ipc_window.ext_hdr); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head; @@ -213,6 +231,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_FW_VERSION: ret = ext_man_get_fw_version(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_WINDOW: + ret = ext_man_get_windows(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); From 4c4a975178ef06324c80baef0e95209f431645a5 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:11 +0300 Subject: [PATCH 360/428] ASoC: SOF: ext_manifest: parse compiler version The compiler version and description can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-6-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 8 ++++++++ sound/soc/sof/loader.c | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index 0001fc5779ef..04359cda92dc 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -59,6 +59,7 @@ struct sof_ext_man_header { enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, + SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, }; /* extended manifest element header */ @@ -84,4 +85,11 @@ struct sof_ext_man_window { struct sof_ipc_window ipc_window; } __packed; +/* Used C compiler description */ +struct sof_ext_man_cc_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_cc_version cc_version; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 6e92a1285b91..b94fa5f5d480 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -49,6 +49,14 @@ static int get_cc_info(struct snd_sof_dev *sdev, const struct sof_ipc_cc_version *cc = container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); + if (sdev->cc_version) { + if (memcmp(sdev->cc_version, cc, cc->ext_hdr.hdr.size)) { + dev_err(sdev->dev, "error: receive diverged cc_version descriptions"); + return -EINVAL; + } + return 0; + } + dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", cc->name, cc->major, cc->minor, cc->micro, cc->desc, cc->optim); @@ -158,6 +166,16 @@ static int ext_man_get_windows(struct snd_sof_dev *sdev, return get_ext_windows(sdev, &w->ipc_window.ext_hdr); } +static int ext_man_get_cc_info(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_cc_version *cc; + + cc = container_of(hdr, struct sof_ext_man_cc_version, hdr); + + return get_cc_info(sdev, &cc->cc_version.ext_hdr); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head; @@ -234,6 +252,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_WINDOW: ret = ext_man_get_windows(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_CC_VERSION: + ret = ext_man_get_cc_info(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); From a6e3f4f34cdbf0ae33731cff047542982a1195b0 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 18 May 2020 09:50:38 +0900 Subject: [PATCH 361/428] ASoC: max98390: Added Amplifier Driver This is the initial amplifier driver for max98390. Reported-by: kbuild test robot Signed-off-by: Steve Lee Link: https://lore.kernel.org/r/20200518005038.21074-1-steves.lee@maximintegrated.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/max98390.c | 1040 +++++++++++++++++++++++++++++++++++ sound/soc/codecs/max98390.h | 663 ++++++++++++++++++++++ 4 files changed, 1710 insertions(+) create mode 100644 sound/soc/codecs/max98390.c create mode 100644 sound/soc/codecs/max98390.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 2d4f1b4bc011..683e0a94fd45 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -116,6 +116,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_MAX98926 imply SND_SOC_MAX98927 imply SND_SOC_MAX98373 + imply SND_SOC_MAX98390 imply SND_SOC_MAX9850 imply SND_SOC_MAX9860 imply SND_SOC_MAX9759 @@ -867,6 +868,10 @@ config SND_SOC_MAX98373 tristate "Maxim Integrated MAX98373 Speaker Amplifier" depends on I2C +config SND_SOC_MAX98390 + tristate "Maxim Integrated MAX98390 Speaker Amplifier" + depends on I2C + config SND_SOC_MAX9850 tristate depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index a603532c7af5..2a5a2ad14895 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -115,6 +115,7 @@ snd-soc-max98925-objs := max98925.o snd-soc-max98926-objs := max98926.o snd-soc-max98927-objs := max98927.o snd-soc-max98373-objs := max98373.o +snd-soc-max98390-objs := max98390.o snd-soc-max9850-objs := max9850.o snd-soc-max9860-objs := max9860.o snd-soc-mc13783-objs := mc13783.o @@ -416,6 +417,7 @@ obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o +obj-$(CONFIG_SND_SOC_MAX98390) += snd-soc-max98390.o obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c new file mode 100644 index 000000000000..b9ce44dda886 --- /dev/null +++ b/sound/soc/codecs/max98390.c @@ -0,0 +1,1040 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * max98390.c -- MAX98390 ALSA Soc Audio driver + * + * Copyright (C) 2020 Maxim Integrated Products + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "max98390.h" + +static struct reg_default max98390_reg_defaults[] = { + {MAX98390_INT_EN1, 0xf0}, + {MAX98390_INT_EN2, 0x00}, + {MAX98390_INT_EN3, 0x00}, + {MAX98390_INT_FLAG_CLR1, 0x00}, + {MAX98390_INT_FLAG_CLR2, 0x00}, + {MAX98390_INT_FLAG_CLR3, 0x00}, + {MAX98390_IRQ_CTRL, 0x01}, + {MAX98390_CLK_MON, 0x6d}, + {MAX98390_DAT_MON, 0x03}, + {MAX98390_WDOG_CTRL, 0x00}, + {MAX98390_WDOG_RST, 0x00}, + {MAX98390_MEAS_ADC_THERM_WARN_THRESH, 0x75}, + {MAX98390_MEAS_ADC_THERM_SHDN_THRESH, 0x8c}, + {MAX98390_MEAS_ADC_THERM_HYSTERESIS, 0x08}, + {MAX98390_PIN_CFG, 0x55}, + {MAX98390_PCM_RX_EN_A, 0x00}, + {MAX98390_PCM_RX_EN_B, 0x00}, + {MAX98390_PCM_TX_EN_A, 0x00}, + {MAX98390_PCM_TX_EN_B, 0x00}, + {MAX98390_PCM_TX_HIZ_CTRL_A, 0xff}, + {MAX98390_PCM_TX_HIZ_CTRL_B, 0xff}, + {MAX98390_PCM_CH_SRC_1, 0x00}, + {MAX98390_PCM_CH_SRC_2, 0x00}, + {MAX98390_PCM_CH_SRC_3, 0x00}, + {MAX98390_PCM_MODE_CFG, 0xc0}, + {MAX98390_PCM_MASTER_MODE, 0x1c}, + {MAX98390_PCM_CLK_SETUP, 0x44}, + {MAX98390_PCM_SR_SETUP, 0x08}, + {MAX98390_ICC_RX_EN_A, 0x00}, + {MAX98390_ICC_RX_EN_B, 0x00}, + {MAX98390_ICC_TX_EN_A, 0x00}, + {MAX98390_ICC_TX_EN_B, 0x00}, + {MAX98390_ICC_HIZ_MANUAL_MODE, 0x00}, + {MAX98390_ICC_TX_HIZ_EN_A, 0x00}, + {MAX98390_ICC_TX_HIZ_EN_B, 0x00}, + {MAX98390_ICC_LNK_EN, 0x00}, + {MAX98390_R2039_AMP_DSP_CFG, 0x0f}, + {MAX98390_R203A_AMP_EN, 0x81}, + {MAX98390_TONE_GEN_DC_CFG, 0x00}, + {MAX98390_SPK_SRC_SEL, 0x00}, + {MAX98390_SSM_CFG, 0x85}, + {MAX98390_MEAS_EN, 0x03}, + {MAX98390_MEAS_DSP_CFG, 0x0f}, + {MAX98390_BOOST_CTRL0, 0x1c}, + {MAX98390_BOOST_CTRL3, 0x01}, + {MAX98390_BOOST_CTRL1, 0x40}, + {MAX98390_MEAS_ADC_CFG, 0x07}, + {MAX98390_MEAS_ADC_BASE_MSB, 0x00}, + {MAX98390_MEAS_ADC_BASE_LSB, 0x23}, + {MAX98390_ADC_CH0_DIVIDE, 0x00}, + {MAX98390_ADC_CH1_DIVIDE, 0x00}, + {MAX98390_ADC_CH2_DIVIDE, 0x00}, + {MAX98390_ADC_CH0_FILT_CFG, 0x00}, + {MAX98390_ADC_CH1_FILT_CFG, 0x00}, + {MAX98390_ADC_CH2_FILT_CFG, 0x00}, + {MAX98390_PWR_GATE_CTL, 0x2c}, + {MAX98390_BROWNOUT_EN, 0x00}, + {MAX98390_BROWNOUT_INFINITE_HOLD, 0x00}, + {MAX98390_BROWNOUT_INFINITE_HOLD_CLR, 0x00}, + {MAX98390_BROWNOUT_LVL_HOLD, 0x00}, + {MAX98390_BROWNOUT_LVL1_THRESH, 0x00}, + {MAX98390_BROWNOUT_LVL2_THRESH, 0x00}, + {MAX98390_BROWNOUT_LVL3_THRESH, 0x00}, + {MAX98390_BROWNOUT_LVL4_THRESH, 0x00}, + {MAX98390_BROWNOUT_THRESH_HYSTERYSIS, 0x00}, + {MAX98390_BROWNOUT_AMP_LIMITER_ATK_REL, 0x1f}, + {MAX98390_BROWNOUT_AMP_GAIN_ATK_REL, 0x00}, + {MAX98390_BROWNOUT_AMP1_CLIP_MODE, 0x00}, + {MAX98390_BROWNOUT_LVL1_CUR_LIMIT, 0x00}, + {MAX98390_BROWNOUT_LVL1_AMP1_CTRL1, 0x00}, + {MAX98390_BROWNOUT_LVL1_AMP1_CTRL2, 0x00}, + {MAX98390_BROWNOUT_LVL1_AMP1_CTRL3, 0x00}, + {MAX98390_BROWNOUT_LVL2_CUR_LIMIT, 0x00}, + {MAX98390_BROWNOUT_LVL2_AMP1_CTRL1, 0x00}, + {MAX98390_BROWNOUT_LVL2_AMP1_CTRL2, 0x00}, + {MAX98390_BROWNOUT_LVL2_AMP1_CTRL3, 0x00}, + {MAX98390_BROWNOUT_LVL3_CUR_LIMIT, 0x00}, + {MAX98390_BROWNOUT_LVL3_AMP1_CTRL1, 0x00}, + {MAX98390_BROWNOUT_LVL3_AMP1_CTRL2, 0x00}, + {MAX98390_BROWNOUT_LVL3_AMP1_CTRL3, 0x00}, + {MAX98390_BROWNOUT_LVL4_CUR_LIMIT, 0x00}, + {MAX98390_BROWNOUT_LVL4_AMP1_CTRL1, 0x00}, + {MAX98390_BROWNOUT_LVL4_AMP1_CTRL2, 0x00}, + {MAX98390_BROWNOUT_LVL4_AMP1_CTRL3, 0x00}, + {MAX98390_BROWNOUT_ILIM_HLD, 0x00}, + {MAX98390_BROWNOUT_LIM_HLD, 0x00}, + {MAX98390_BROWNOUT_CLIP_HLD, 0x00}, + {MAX98390_BROWNOUT_GAIN_HLD, 0x00}, + {MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0f}, + {MAX98390_ENV_TRACK_BOOST_VOUT_DELAY, 0x80}, + {MAX98390_ENV_TRACK_REL_RATE, 0x07}, + {MAX98390_ENV_TRACK_HOLD_RATE, 0x07}, + {MAX98390_ENV_TRACK_CTRL, 0x01}, + {MAX98390_BOOST_BYPASS1, 0x49}, + {MAX98390_BOOST_BYPASS2, 0x2b}, + {MAX98390_BOOST_BYPASS3, 0x08}, + {MAX98390_FET_SCALING1, 0x00}, + {MAX98390_FET_SCALING2, 0x03}, + {MAX98390_FET_SCALING3, 0x00}, + {MAX98390_FET_SCALING4, 0x07}, + {MAX98390_SPK_SPEEDUP, 0x00}, + {DSMIG_WB_DRC_RELEASE_TIME_1, 0x00}, + {DSMIG_WB_DRC_RELEASE_TIME_2, 0x00}, + {DSMIG_WB_DRC_ATTACK_TIME_1, 0x00}, + {DSMIG_WB_DRC_ATTACK_TIME_2, 0x00}, + {DSMIG_WB_DRC_COMPRESSION_RATIO, 0x00}, + {DSMIG_WB_DRC_COMPRESSION_THRESHOLD, 0x00}, + {DSMIG_WB_DRC_MAKEUPGAIN, 0x00}, + {DSMIG_WB_DRC_NOISE_GATE_THRESHOLD, 0x00}, + {DSMIG_WBDRC_HPF_ENABLE, 0x00}, + {DSMIG_WB_DRC_TEST_SMOOTHER_OUT_EN, 0x00}, + {DSMIG_PPR_THRESHOLD, 0x00}, + {DSM_STEREO_BASS_CHANNEL_SELECT, 0x00}, + {DSM_TPROT_THRESHOLD_BYTE0, 0x00}, + {DSM_TPROT_THRESHOLD_BYTE1, 0x00}, + {DSM_TPROT_ROOM_TEMPERATURE_BYTE0, 0x00}, + {DSM_TPROT_ROOM_TEMPERATURE_BYTE1, 0x00}, + {DSM_TPROT_RECIP_RDC_ROOM_BYTE0, 0x00}, + {DSM_TPROT_RECIP_RDC_ROOM_BYTE1, 0x00}, + {DSM_TPROT_RECIP_RDC_ROOM_BYTE2, 0x00}, + {DSM_TPROT_RECIP_TCONST_BYTE0, 0x00}, + {DSM_TPROT_RECIP_TCONST_BYTE1, 0x00}, + {DSM_TPROT_RECIP_TCONST_BYTE2, 0x00}, + {DSM_THERMAL_ATTENUATION_SETTINGS, 0x00}, + {DSM_THERMAL_PILOT_TONE_ATTENUATION, 0x00}, + {DSM_TPROT_PG_TEMP_THRESH_BYTE0, 0x00}, + {DSM_TPROT_PG_TEMP_THRESH_BYTE1, 0x00}, + {DSMIG_DEBUZZER_THRESHOLD, 0x00}, + {DSMIG_DEBUZZER_ALPHA_COEF_TEST_ONLY, 0x08}, + {DSM_VOL_ENA, 0x20}, + {DSM_VOL_CTRL, 0xa0}, + {DSMIG_EN, 0x00}, + {MAX98390_R23E1_DSP_GLOBAL_EN, 0x00}, + {MAX98390_R23FF_GLOBAL_EN, 0x00}, +}; + +static int max98390_dsm_calibrate(struct snd_soc_component *component); + +static int max98390_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + unsigned int mode; + unsigned int format; + unsigned int invert = 0; + + dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + mode = MAX98390_PCM_MASTER_MODE_SLAVE; + break; + case SND_SOC_DAIFMT_CBM_CFM: + max98390->master = true; + mode = MAX98390_PCM_MASTER_MODE_MASTER; + break; + default: + dev_err(component->dev, "DAI clock mode unsupported\n"); + return -EINVAL; + } + + regmap_update_bits(max98390->regmap, + MAX98390_PCM_MASTER_MODE, + MAX98390_PCM_MASTER_MODE_MASK, + mode); + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + invert = MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE; + break; + default: + dev_err(component->dev, "DAI invert mode unsupported\n"); + return -EINVAL; + } + + regmap_update_bits(max98390->regmap, + MAX98390_PCM_MODE_CFG, + MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE, + invert); + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + format = MAX98390_PCM_FORMAT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + format = MAX98390_PCM_FORMAT_LJ; + break; + case SND_SOC_DAIFMT_DSP_A: + format = MAX98390_PCM_FORMAT_TDM_MODE1; + break; + case SND_SOC_DAIFMT_DSP_B: + format = MAX98390_PCM_FORMAT_TDM_MODE0; + break; + default: + return -EINVAL; + } + + regmap_update_bits(max98390->regmap, + MAX98390_PCM_MODE_CFG, + MAX98390_PCM_MODE_CFG_FORMAT_MASK, + format << MAX98390_PCM_MODE_CFG_FORMAT_SHIFT); + + return 0; +} + +static int max98390_get_bclk_sel(int bclk) +{ + int i; + /* BCLKs per LRCLK */ + static int bclk_sel_table[] = { + 32, 48, 64, 96, 128, 192, 256, 320, 384, 512, + }; + /* match BCLKs per LRCLK */ + for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { + if (bclk_sel_table[i] == bclk) + return i + 2; + } + return 0; +} + +static int max98390_set_clock(struct snd_soc_component *component, + struct snd_pcm_hw_params *params) +{ + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + /* codec MCLK rate in master mode */ + static int rate_table[] = { + 5644800, 6000000, 6144000, 6500000, + 9600000, 11289600, 12000000, 12288000, + 13000000, 19200000, + }; + /* BCLK/LRCLK ratio calculation */ + int blr_clk_ratio = params_channels(params) + * snd_pcm_format_width(params_format(params)); + int value; + + if (max98390->master) { + int i; + /* match rate to closest value */ + for (i = 0; i < ARRAY_SIZE(rate_table); i++) { + if (rate_table[i] >= max98390->sysclk) + break; + } + if (i == ARRAY_SIZE(rate_table)) { + dev_err(component->dev, "failed to find proper clock rate.\n"); + return -EINVAL; + } + + regmap_update_bits(max98390->regmap, + MAX98390_PCM_MASTER_MODE, + MAX98390_PCM_MASTER_MODE_MCLK_MASK, + i << MAX98390_PCM_MASTER_MODE_MCLK_RATE_SHIFT); + } + + if (!max98390->tdm_mode) { + /* BCLK configuration */ + value = max98390_get_bclk_sel(blr_clk_ratio); + if (!value) { + dev_err(component->dev, "format unsupported %d\n", + params_format(params)); + return -EINVAL; + } + + regmap_update_bits(max98390->regmap, + MAX98390_PCM_CLK_SETUP, + MAX98390_PCM_CLK_SETUP_BSEL_MASK, + value); + } + return 0; +} + +static int max98390_dai_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 max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + unsigned int sampling_rate; + unsigned int chan_sz; + + /* pcm mode configuration */ + switch (snd_pcm_format_width(params_format(params))) { + case 16: + chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_16; + break; + case 24: + chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_24; + break; + case 32: + chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_32; + break; + default: + dev_err(component->dev, "format unsupported %d\n", + params_format(params)); + goto err; + } + + regmap_update_bits(max98390->regmap, + MAX98390_PCM_MODE_CFG, + MAX98390_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + + dev_dbg(component->dev, "format supported %d", + params_format(params)); + + /* sampling rate configuration */ + switch (params_rate(params)) { + case 8000: + sampling_rate = MAX98390_PCM_SR_SET1_SR_8000; + break; + case 11025: + sampling_rate = MAX98390_PCM_SR_SET1_SR_11025; + break; + case 12000: + sampling_rate = MAX98390_PCM_SR_SET1_SR_12000; + break; + case 16000: + sampling_rate = MAX98390_PCM_SR_SET1_SR_16000; + break; + case 22050: + sampling_rate = MAX98390_PCM_SR_SET1_SR_22050; + break; + case 24000: + sampling_rate = MAX98390_PCM_SR_SET1_SR_24000; + break; + case 32000: + sampling_rate = MAX98390_PCM_SR_SET1_SR_32000; + break; + case 44100: + sampling_rate = MAX98390_PCM_SR_SET1_SR_44100; + break; + case 48000: + sampling_rate = MAX98390_PCM_SR_SET1_SR_48000; + break; + default: + dev_err(component->dev, "rate %d not supported\n", + params_rate(params)); + goto err; + } + + /* set DAI_SR to correct LRCLK frequency */ + regmap_update_bits(max98390->regmap, + MAX98390_PCM_SR_SETUP, + MAX98390_PCM_SR_SET1_SR_MASK, + sampling_rate); + + return max98390_set_clock(component, params); +err: + return -EINVAL; +} + +static int max98390_dai_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 max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + int bsel; + unsigned int chan_sz; + + if (!tx_mask && !rx_mask && !slots && !slot_width) + max98390->tdm_mode = false; + else + max98390->tdm_mode = true; + + dev_dbg(component->dev, + "Tdm mode : %d\n", max98390->tdm_mode); + + /* BCLK configuration */ + bsel = max98390_get_bclk_sel(slots * slot_width); + if (!bsel) { + dev_err(component->dev, "BCLK %d not supported\n", + slots * slot_width); + return -EINVAL; + } + + regmap_update_bits(max98390->regmap, + MAX98390_PCM_CLK_SETUP, + MAX98390_PCM_CLK_SETUP_BSEL_MASK, + bsel); + + /* Channel size configuration */ + switch (slot_width) { + case 16: + chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_16; + break; + case 24: + chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_24; + break; + case 32: + chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_32; + break; + default: + dev_err(component->dev, "format unsupported %d\n", + slot_width); + return -EINVAL; + } + + regmap_update_bits(max98390->regmap, + MAX98390_PCM_MODE_CFG, + MAX98390_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + + /* Rx slot configuration */ + regmap_write(max98390->regmap, + MAX98390_PCM_RX_EN_A, + rx_mask & 0xFF); + regmap_write(max98390->regmap, + MAX98390_PCM_RX_EN_B, + (rx_mask & 0xFF00) >> 8); + + /* Tx slot Hi-Z configuration */ + regmap_write(max98390->regmap, + MAX98390_PCM_TX_HIZ_CTRL_A, + ~tx_mask & 0xFF); + regmap_write(max98390->regmap, + MAX98390_PCM_TX_HIZ_CTRL_B, + (~tx_mask & 0xFF00) >> 8); + + return 0; +} + +static int max98390_dai_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = dai->component; + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + max98390->sysclk = freq; + return 0; +} + +static const struct snd_soc_dai_ops max98390_dai_ops = { + .set_sysclk = max98390_dai_set_sysclk, + .set_fmt = max98390_dai_set_fmt, + .hw_params = max98390_dai_hw_params, + .set_tdm_slot = max98390_dai_tdm_slot, +}; + +static int max98390_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); + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(max98390->regmap, + MAX98390_R203A_AMP_EN, + MAX98390_AMP_EN_MASK, 1); + regmap_update_bits(max98390->regmap, + MAX98390_R23FF_GLOBAL_EN, + MAX98390_GLOBAL_EN_MASK, 1); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(max98390->regmap, + MAX98390_R23FF_GLOBAL_EN, + MAX98390_GLOBAL_EN_MASK, 0); + regmap_update_bits(max98390->regmap, + MAX98390_R203A_AMP_EN, + MAX98390_AMP_EN_MASK, 0); + break; + } + return 0; +} + +static const char * const max98390_switch_text[] = { + "Left", "Right", "LeftRight"}; + +static const char * const max98390_boost_voltage_text[] = { + "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V", + "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V", + "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V", + "9.5V", "9.625V", "9.75V", "9.875V", "10V" +}; + +static SOC_ENUM_SINGLE_DECL(max98390_boost_voltage, + MAX98390_BOOST_CTRL0, 0, + max98390_boost_voltage_text); + +static DECLARE_TLV_DB_SCALE(max98390_spk_tlv, 300, 300, 0); +static DECLARE_TLV_DB_SCALE(max98390_digital_tlv, -8000, 50, 0); + +static const char * const max98390_current_limit_text[] = { + "0.00A", "0.50A", "1.00A", "1.05A", "1.10A", "1.15A", "1.20A", "1.25A", + "1.30A", "1.35A", "1.40A", "1.45A", "1.50A", "1.55A", "1.60A", "1.65A", + "1.70A", "1.75A", "1.80A", "1.85A", "1.90A", "1.95A", "2.00A", "2.05A", + "2.10A", "2.15A", "2.20A", "2.25A", "2.30A", "2.35A", "2.40A", "2.45A", + "2.50A", "2.55A", "2.60A", "2.65A", "2.70A", "2.75A", "2.80A", "2.85A", + "2.90A", "2.95A", "3.00A", "3.05A", "3.10A", "3.15A", "3.20A", "3.25A", + "3.30A", "3.35A", "3.40A", "3.45A", "3.50A", "3.55A", "3.60A", "3.65A", + "3.70A", "3.75A", "3.80A", "3.85A", "3.90A", "3.95A", "4.00A", "4.05A", + "4.10A" +}; + +static SOC_ENUM_SINGLE_DECL(max98390_current_limit, + MAX98390_BOOST_CTRL1, 0, + max98390_current_limit_text); + +static int max98390_ref_rdc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + max98390->ref_rdc_value = ucontrol->value.integer.value[0]; + + regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0, + max98390->ref_rdc_value & 0x000000ff); + regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE1, + (max98390->ref_rdc_value >> 8) & 0x000000ff); + regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE2, + (max98390->ref_rdc_value >> 16) & 0x000000ff); + + return 0; +} + +static int max98390_ref_rdc_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = max98390->ref_rdc_value; + + return 0; +} + +static int max98390_ambient_temp_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + max98390->ambient_temp_value = ucontrol->value.integer.value[0]; + + regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE1, + (max98390->ambient_temp_value >> 8) & 0x000000ff); + regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE0, + (max98390->ambient_temp_value) & 0x000000ff); + + return 0; +} + +static int max98390_ambient_temp_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = max98390->ambient_temp_value; + + return 0; +} + +static int max98390_adaptive_rdc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + dev_warn(component->dev, "Put adaptive rdc not supported\n"); + + return 0; +} + +static int max98390_adaptive_rdc_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int rdc, rdc0; + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE1, &rdc); + regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE0, &rdc0); + ucontrol->value.integer.value[0] = rdc0 | rdc << 8; + + return 0; +} + +static int max98390_dsm_calib_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + /* Do nothing */ + return 0; +} + +static int max98390_dsm_calib_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + max98390_dsm_calibrate(component); + + return 0; +} + +static const struct snd_kcontrol_new max98390_snd_controls[] = { + SOC_SINGLE_TLV("Digital Volume", DSM_VOL_CTRL, + 0, 184, 0, + max98390_digital_tlv), + SOC_SINGLE_TLV("Speaker Volume", MAX98390_R203D_SPK_GAIN, + 0, 6, 0, + max98390_spk_tlv), + SOC_SINGLE("Ramp Up Bypass Switch", MAX98390_R2039_AMP_DSP_CFG, + MAX98390_AMP_DSP_CFG_RMP_UP_SHIFT, 1, 0), + SOC_SINGLE("Ramp Down Bypass Switch", MAX98390_R2039_AMP_DSP_CFG, + MAX98390_AMP_DSP_CFG_RMP_DN_SHIFT, 1, 0), + SOC_SINGLE("Boost Clock Phase", MAX98390_BOOST_CTRL3, + MAX98390_BOOST_CLK_PHASE_CFG_SHIFT, 3, 0), + SOC_ENUM("Boost Output Voltage", max98390_boost_voltage), + SOC_ENUM("Current Limit", max98390_current_limit), + SOC_SINGLE_EXT("DSM Rdc", SND_SOC_NOPM, 0, 0xffffff, 0, + max98390_ref_rdc_get, max98390_ref_rdc_put), + SOC_SINGLE_EXT("DSM Ambient Temp", SND_SOC_NOPM, 0, 0xffff, 0, + max98390_ambient_temp_get, max98390_ambient_temp_put), + SOC_SINGLE_EXT("DSM Adaptive Rdc", SND_SOC_NOPM, 0, 0xffff, 0, + max98390_adaptive_rdc_get, max98390_adaptive_rdc_put), + SOC_SINGLE_EXT("DSM Calibration", SND_SOC_NOPM, 0, 1, 0, + max98390_dsm_calib_get, max98390_dsm_calib_put), +}; + +static const struct soc_enum dai_sel_enum = + SOC_ENUM_SINGLE(MAX98390_PCM_CH_SRC_1, + MAX98390_PCM_RX_CH_SRC_SHIFT, + 3, max98390_switch_text); + +static const struct snd_kcontrol_new max98390_dai_controls = + SOC_DAPM_ENUM("DAI Sel", dai_sel_enum); + +static const struct snd_soc_dapm_widget max98390_dapm_widgets[] = { + SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", + MAX98390_R203A_AMP_EN, 0, 0, max98390_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, + &max98390_dai_controls), + SND_SOC_DAPM_OUTPUT("BE_OUT"), +}; + +static const struct snd_soc_dapm_route max98390_audio_map[] = { + /* Plabyack */ + {"DAI Sel Mux", "Left", "Amp Enable"}, + {"DAI Sel Mux", "Right", "Amp Enable"}, + {"DAI Sel Mux", "LeftRight", "Amp Enable"}, + {"BE_OUT", NULL, "DAI Sel Mux"}, +}; + +static bool max98390_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98390_SOFTWARE_RESET ... MAX98390_INT_EN3: + case MAX98390_IRQ_CTRL ... MAX98390_WDOG_CTRL: + case MAX98390_MEAS_ADC_THERM_WARN_THRESH + ... MAX98390_BROWNOUT_INFINITE_HOLD: + case MAX98390_BROWNOUT_LVL_HOLD ... THERMAL_COILTEMP_RD_BACK_BYTE0: + case DSMIG_DEBUZZER_THRESHOLD ... MAX98390_R24FF_REV_ID: + return true; + default: + return false; + } +}; + +static bool max98390_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98390_SOFTWARE_RESET ... MAX98390_INT_EN3: + case MAX98390_MEAS_ADC_CH0_READ ... MAX98390_MEAS_ADC_CH2_READ: + case MAX98390_PWR_GATE_STATUS ... MAX98390_BROWNOUT_STATUS: + case MAX98390_BROWNOUT_LOWEST_STATUS: + case MAX98390_ENV_TRACK_BOOST_VOUT_READ: + case DSM_STBASS_HPF_B0_BYTE0 ... DSM_DEBUZZER_ATTACK_TIME_BYTE2: + case THERMAL_RDC_RD_BACK_BYTE1 ... THERMAL_COILTEMP_RD_BACK_BYTE0: + case DSM_THERMAL_GAIN ... DSM_WBDRC_GAIN: + return true; + default: + return false; + } +} + +#define MAX98390_RATES SNDRV_PCM_RATE_8000_48000 + +#define MAX98390_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver max98390_dai[] = { + { + .name = "max98390-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98390_RATES, + .formats = MAX98390_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98390_RATES, + .formats = MAX98390_FORMATS, + }, + .ops = &max98390_dai_ops, + } +}; + +static int max98390_dsm_init(struct snd_soc_component *component) +{ + int ret; + char filename[128]; + const char *vendor, *product; + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + const struct firmware *fw; + char *dsm_param; + + vendor = dmi_get_system_info(DMI_SYS_VENDOR); + product = dmi_get_system_info(DMI_PRODUCT_NAME); + + if (vendor && product) { + snprintf(filename, sizeof(filename), "dsm_param_%s_%s.bin", + vendor, product); + } else { + sprintf(filename, "dsm_param.bin"); + } + ret = request_firmware(&fw, filename, component->dev); + if (ret) { + ret = request_firmware(&fw, "dsm_param.bin", component->dev); + if (ret) + goto err; + } + + dev_dbg(component->dev, + "max98390: param fw size %ld\n", + fw->size); + dsm_param = (char *)fw->data; + dsm_param += MAX98390_DSM_PAYLOAD_OFFSET; + regmap_bulk_write(max98390->regmap, DSM_EQ_BQ1_B0_BYTE0, + dsm_param, + fw->size - MAX98390_DSM_PAYLOAD_OFFSET); + release_firmware(fw); + regmap_write(max98390->regmap, MAX98390_R23E1_DSP_GLOBAL_EN, 0x01); + +err: + return ret; +} + +static int max98390_dsm_calibrate(struct snd_soc_component *component) +{ + unsigned int rdc, rdc_cal_result, temp; + unsigned int rdc_integer, rdc_factor; + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x81); + regmap_write(max98390->regmap, MAX98390_R23FF_GLOBAL_EN, 0x01); + + regmap_read(max98390->regmap, + THERMAL_RDC_RD_BACK_BYTE1, &rdc); + regmap_read(max98390->regmap, + THERMAL_RDC_RD_BACK_BYTE0, &rdc_cal_result); + rdc_cal_result |= (rdc << 8) & 0x0000FFFF; + if (rdc_cal_result) + max98390->ref_rdc_value = 268435456U / rdc_cal_result; + + regmap_read(max98390->regmap, MAX98390_MEAS_ADC_CH2_READ, &temp); + max98390->ambient_temp_value = temp * 52 - 1188; + + rdc_integer = rdc_cal_result * 937 / 65536; + rdc_factor = ((rdc_cal_result * 937 * 100) / 65536) + - (rdc_integer * 100); + + dev_info(component->dev, "rdc resistance about %d.%02d ohm, reg=0x%X temp reg=0x%X\n", + rdc_integer, rdc_factor, rdc_cal_result, temp); + + regmap_write(max98390->regmap, MAX98390_R23FF_GLOBAL_EN, 0x00); + regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80); + + return 0; +} + +static int max98390_probe(struct snd_soc_component *component) +{ + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + regmap_write(max98390->regmap, MAX98390_SOFTWARE_RESET, 0x01); + /* Sleep reset settle time */ + msleep(20); + /* Update dsm bin param */ + max98390_dsm_init(component); + + /* Amp Setting */ + regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f); + regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03); + regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x2d); + regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); + regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); + regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); + + /* Dsm Setting */ + regmap_write(max98390->regmap, DSM_VOL_CTRL, 0x94); + regmap_write(max98390->regmap, DSMIG_EN, 0x19); + regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80); + if (max98390->ref_rdc_value) { + regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0, + max98390->ref_rdc_value & 0x000000ff); + regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE1, + (max98390->ref_rdc_value >> 8) & 0x000000ff); + regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE2, + (max98390->ref_rdc_value >> 16) & 0x000000ff); + } + if (max98390->ambient_temp_value) { + regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE1, + (max98390->ambient_temp_value >> 8) & 0x000000ff); + regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE0, + (max98390->ambient_temp_value) & 0x000000ff); + } + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int max98390_suspend(struct device *dev) +{ + struct max98390_priv *max98390 = dev_get_drvdata(dev); + + dev_dbg(dev, "%s:Enter\n", __func__); + + regcache_cache_only(max98390->regmap, true); + regcache_mark_dirty(max98390->regmap); + + return 0; +} + +static int max98390_resume(struct device *dev) +{ + struct max98390_priv *max98390 = dev_get_drvdata(dev); + + dev_dbg(dev, "%s:Enter\n", __func__); + + regcache_cache_only(max98390->regmap, false); + regcache_sync(max98390->regmap); + + return 0; +} +#endif + +static const struct dev_pm_ops max98390_pm = { + SET_SYSTEM_SLEEP_PM_OPS(max98390_suspend, max98390_resume) +}; + +static const struct snd_soc_component_driver soc_codec_dev_max98390 = { + .probe = max98390_probe, + .controls = max98390_snd_controls, + .num_controls = ARRAY_SIZE(max98390_snd_controls), + .dapm_widgets = max98390_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98390_dapm_widgets), + .dapm_routes = max98390_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98390_audio_map), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct regmap_config max98390_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = MAX98390_R24FF_REV_ID, + .reg_defaults = max98390_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(max98390_reg_defaults), + .readable_reg = max98390_readable_register, + .volatile_reg = max98390_volatile_reg, + .cache_type = REGCACHE_RBTREE, +}; + +#ifdef CONFIG_OF +static const struct of_device_id max98390_dt_ids[] = { + { .compatible = "maxim,max98390", }, + { } +}; +MODULE_DEVICE_TABLE(of, max98390_dt_ids); +#endif + +static int max98390_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + int ret = 0; + int reg = 0; + + struct max98390_priv *max98390 = NULL; + struct i2c_adapter *adapter = to_i2c_adapter(i2c->dev.parent); + + ret = i2c_check_functionality(adapter, + I2C_FUNC_SMBUS_BYTE + | I2C_FUNC_SMBUS_BYTE_DATA); + if (!ret) { + dev_err(&i2c->dev, "I2C check functionality failed\n"); + return -ENXIO; + } + + max98390 = devm_kzalloc(&i2c->dev, sizeof(*max98390), GFP_KERNEL); + if (!max98390) { + ret = -ENOMEM; + return ret; + } + i2c_set_clientdata(i2c, max98390); + + ret = device_property_read_u32(&i2c->dev, "maxim,temperature_calib", + &max98390->ambient_temp_value); + if (ret) { + dev_info(&i2c->dev, + "no optional property 'temperature_calib' found, default:\n"); + } + ret = device_property_read_u32(&i2c->dev, "maxim,r0_calib", + &max98390->ref_rdc_value); + if (ret) { + dev_info(&i2c->dev, + "no optional property 'r0_calib' found, default:\n"); + } + + dev_info(&i2c->dev, + "%s: r0_calib: 0x%x,temperature_calib: 0x%x", + __func__, max98390->ref_rdc_value, + max98390->ambient_temp_value); + + /* regmap initialization */ + max98390->regmap = devm_regmap_init_i2c(i2c, &max98390_regmap); + if (IS_ERR(max98390->regmap)) { + ret = PTR_ERR(max98390->regmap); + dev_err(&i2c->dev, + "Failed to allocate regmap: %d\n", ret); + return ret; + } + + /* Check Revision ID */ + ret = regmap_read(max98390->regmap, + MAX98390_R24FF_REV_ID, ®); + if (ret) { + dev_err(&i2c->dev, + "ret=%d, Failed to read: 0x%02X\n", + ret, MAX98390_R24FF_REV_ID); + return ret; + } + dev_info(&i2c->dev, "MAX98390 revisionID: 0x%02X\n", reg); + + ret = devm_snd_soc_register_component(&i2c->dev, + &soc_codec_dev_max98390, + max98390_dai, ARRAY_SIZE(max98390_dai)); + + return ret; +} + +static const struct i2c_device_id max98390_i2c_id[] = { + { "max98390", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, max98390_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id max98390_of_match[] = { + { .compatible = "maxim,max98390", }, + {} +}; +MODULE_DEVICE_TABLE(of, max98390_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id max98390_acpi_match[] = { + { "MX98390", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, max98390_acpi_match); +#endif + +static struct i2c_driver max98390_i2c_driver = { + .driver = { + .name = "max98390", + .of_match_table = of_match_ptr(max98390_of_match), + .acpi_match_table = ACPI_PTR(max98390_acpi_match), + .pm = &max98390_pm, + }, + .probe = max98390_i2c_probe, + .id_table = max98390_i2c_id, +}; + +module_i2c_driver(max98390_i2c_driver) + +MODULE_DESCRIPTION("ALSA SoC MAX98390 driver"); +MODULE_AUTHOR("Steve Lee "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98390.h b/sound/soc/codecs/max98390.h new file mode 100644 index 000000000000..f59cb114d957 --- /dev/null +++ b/sound/soc/codecs/max98390.h @@ -0,0 +1,663 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020, Maxim Integrated. + */ + +#ifndef _MAX98390_H +#define _MAX98390_H + +/* MAX98390 Register Address */ +#define MAX98390_SOFTWARE_RESET 0x2000 +#define MAX98390_INT_RAW1 0x2002 +#define MAX98390_INT_RAW2 0x2003 +#define MAX98390_INT_RAW3 0x2004 +#define MAX98390_INT_STATE1 0x2005 +#define MAX98390_INT_STATE2 0x2006 +#define MAX98390_INT_STATE3 0x2007 +#define MAX98390_INT_FLAG1 0x2008 +#define MAX98390_INT_FLAG2 0x2009 +#define MAX98390_INT_FLAG3 0x200a +#define MAX98390_INT_EN1 0x200b +#define MAX98390_INT_EN2 0x200c +#define MAX98390_INT_EN3 0x200d +#define MAX98390_INT_FLAG_CLR1 0x200e +#define MAX98390_INT_FLAG_CLR2 0x200f +#define MAX98390_INT_FLAG_CLR3 0x2010 +#define MAX98390_IRQ_CTRL 0x2011 +#define MAX98390_CLK_MON 0x2012 +#define MAX98390_DAT_MON 0x2014 +#define MAX98390_WDOG_CTRL 0x2015 +#define MAX98390_WDOG_RST 0x2016 +#define MAX98390_MEAS_ADC_THERM_WARN_THRESH 0x2017 +#define MAX98390_MEAS_ADC_THERM_SHDN_THRESH 0x2018 +#define MAX98390_MEAS_ADC_THERM_HYSTERESIS 0x2019 +#define MAX98390_PIN_CFG 0x201a +#define MAX98390_PCM_RX_EN_A 0x201b +#define MAX98390_PCM_RX_EN_B 0x201c +#define MAX98390_PCM_TX_EN_A 0x201d +#define MAX98390_PCM_TX_EN_B 0x201e +#define MAX98390_PCM_TX_HIZ_CTRL_A 0x201f +#define MAX98390_PCM_TX_HIZ_CTRL_B 0x2020 +#define MAX98390_PCM_CH_SRC_1 0x2021 +#define MAX98390_PCM_CH_SRC_2 0x2022 +#define MAX98390_PCM_CH_SRC_3 0x2023 +#define MAX98390_PCM_MODE_CFG 0x2024 +#define MAX98390_PCM_MASTER_MODE 0x2025 +#define MAX98390_PCM_CLK_SETUP 0x2026 +#define MAX98390_PCM_SR_SETUP 0x2027 +#define MAX98390_ICC_RX_EN_A 0x202c +#define MAX98390_ICC_RX_EN_B 0x202d +#define MAX98390_ICC_TX_EN_A 0x202e +#define MAX98390_ICC_TX_EN_B 0x202f +#define MAX98390_ICC_HIZ_MANUAL_MODE 0x2030 +#define MAX98390_ICC_TX_HIZ_EN_A 0x2031 +#define MAX98390_ICC_TX_HIZ_EN_B 0x2032 +#define MAX98390_ICC_LNK_EN 0x2033 +#define MAX98390_R2039_AMP_DSP_CFG 0x2039 +#define MAX98390_R203A_AMP_EN 0x203a +#define MAX98390_TONE_GEN_DC_CFG 0x203b +#define MAX98390_SPK_SRC_SEL 0x203c +#define MAX98390_R203D_SPK_GAIN 0x203d +#define MAX98390_SSM_CFG 0x203e +#define MAX98390_MEAS_EN 0x203f +#define MAX98390_MEAS_DSP_CFG 0x2040 +#define MAX98390_BOOST_CTRL0 0x2041 +#define MAX98390_BOOST_CTRL3 0x2042 +#define MAX98390_BOOST_CTRL1 0x2043 +#define MAX98390_MEAS_ADC_CFG 0x2044 +#define MAX98390_MEAS_ADC_BASE_MSB 0x2045 +#define MAX98390_MEAS_ADC_BASE_LSB 0x2046 +#define MAX98390_ADC_CH0_DIVIDE 0x2047 +#define MAX98390_ADC_CH1_DIVIDE 0x2048 +#define MAX98390_ADC_CH2_DIVIDE 0x2049 +#define MAX98390_ADC_CH0_FILT_CFG 0x204a +#define MAX98390_ADC_CH1_FILT_CFG 0x204b +#define MAX98390_ADC_CH2_FILT_CFG 0x204c +#define MAX98390_MEAS_ADC_CH0_READ 0x204d +#define MAX98390_MEAS_ADC_CH1_READ 0x204e +#define MAX98390_MEAS_ADC_CH2_READ 0x204f +#define MAX98390_PWR_GATE_CTL 0x2050 +#define MAX98390_PWR_GATE_STATUS 0x2051 +#define MAX98390_VBAT_LOW_STATUS 0x2052 +#define MAX98390_PVDD_LOW_STATUS 0x2053 +#define MAX98390_BROWNOUT_STATUS 0x2054 +#define MAX98390_BROWNOUT_EN 0x2055 +#define MAX98390_BROWNOUT_INFINITE_HOLD 0x2056 +#define MAX98390_BROWNOUT_INFINITE_HOLD_CLR 0x2057 +#define MAX98390_BROWNOUT_LVL_HOLD 0x2058 +#define MAX98390_BROWNOUT_LVL1_THRESH 0x2059 +#define MAX98390_BROWNOUT_LVL2_THRESH 0x205a +#define MAX98390_BROWNOUT_LVL3_THRESH 0x205b +#define MAX98390_BROWNOUT_LVL4_THRESH 0x205c +#define MAX98390_BROWNOUT_THRESH_HYSTERYSIS 0x205d +#define MAX98390_BROWNOUT_AMP_LIMITER_ATK_REL 0x205e +#define MAX98390_BROWNOUT_AMP_GAIN_ATK_REL 0x205f +#define MAX98390_BROWNOUT_AMP1_CLIP_MODE 0x2060 +#define MAX98390_BROWNOUT_LVL1_CUR_LIMIT 0x2061 +#define MAX98390_BROWNOUT_LVL1_AMP1_CTRL1 0x2062 +#define MAX98390_BROWNOUT_LVL1_AMP1_CTRL2 0x2063 +#define MAX98390_BROWNOUT_LVL1_AMP1_CTRL3 0x2064 +#define MAX98390_BROWNOUT_LVL2_CUR_LIMIT 0x2065 +#define MAX98390_BROWNOUT_LVL2_AMP1_CTRL1 0x2066 +#define MAX98390_BROWNOUT_LVL2_AMP1_CTRL2 0x2067 +#define MAX98390_BROWNOUT_LVL2_AMP1_CTRL3 0x2068 +#define MAX98390_BROWNOUT_LVL3_CUR_LIMIT 0x2069 +#define MAX98390_BROWNOUT_LVL3_AMP1_CTRL1 0x206a +#define MAX98390_BROWNOUT_LVL3_AMP1_CTRL2 0x206b +#define MAX98390_BROWNOUT_LVL3_AMP1_CTRL3 0x206c +#define MAX98390_BROWNOUT_LVL4_CUR_LIMIT 0x206d +#define MAX98390_BROWNOUT_LVL4_AMP1_CTRL1 0x206e +#define MAX98390_BROWNOUT_LVL4_AMP1_CTRL2 0x206f +#define MAX98390_BROWNOUT_LVL4_AMP1_CTRL3 0x2070 +#define MAX98390_BROWNOUT_LOWEST_STATUS 0x2071 +#define MAX98390_BROWNOUT_ILIM_HLD 0x2072 +#define MAX98390_BROWNOUT_LIM_HLD 0x2073 +#define MAX98390_BROWNOUT_CLIP_HLD 0x2074 +#define MAX98390_BROWNOUT_GAIN_HLD 0x2075 +#define MAX98390_ENV_TRACK_VOUT_HEADROOM 0x2076 +#define MAX98390_ENV_TRACK_BOOST_VOUT_DELAY 0x2077 +#define MAX98390_ENV_TRACK_REL_RATE 0x2078 +#define MAX98390_ENV_TRACK_HOLD_RATE 0x2079 +#define MAX98390_ENV_TRACK_CTRL 0x207a +#define MAX98390_ENV_TRACK_BOOST_VOUT_READ 0x207b +#define MAX98390_BOOST_BYPASS1 0x207c +#define MAX98390_BOOST_BYPASS2 0x207d +#define MAX98390_BOOST_BYPASS3 0x207e +#define MAX98390_FET_SCALING1 0x207f +#define MAX98390_FET_SCALING2 0x2080 +#define MAX98390_FET_SCALING3 0x2081 +#define MAX98390_FET_SCALING4 0x2082 +#define MAX98390_SPK_SPEEDUP 0x2084 + +#define DSM_STBASS_HPF_B0_BYTE0 0x2101 +#define DSM_STBASS_HPF_B0_BYTE1 0x2102 +#define DSM_STBASS_HPF_B0_BYTE2 0x2103 +#define DSM_STBASS_HPF_B1_BYTE0 0x2105 +#define DSM_STBASS_HPF_B1_BYTE1 0x2106 +#define DSM_STBASS_HPF_B1_BYTE2 0x2107 +#define DSM_STBASS_HPF_B2_BYTE0 0x2109 +#define DSM_STBASS_HPF_B2_BYTE1 0x210a +#define DSM_STBASS_HPF_B2_BYTE2 0x210b +#define DSM_STBASS_HPF_A1_BYTE0 0x210d +#define DSM_STBASS_HPF_A1_BYTE1 0x210e +#define DSM_STBASS_HPF_A1_BYTE2 0x210f +#define DSM_STBASS_HPF_A2_BYTE0 0x2111 +#define DSM_STBASS_HPF_A2_BYTE1 0x2112 +#define DSM_STBASS_HPF_A2_BYTE2 0x2113 +#define DSM_STBASS_LPF_B0_BYTE0 0x2115 +#define DSM_STBASS_LPF_B0_BYTE1 0x2116 +#define DSM_STBASS_LPF_B0_BYTE2 0x2117 +#define DSM_STBASS_LPF_B1_BYTE0 0x2119 +#define DSM_STBASS_LPF_B1_BYTE1 0x211a +#define DSM_STBASS_LPF_B1_BYTE2 0x211b +#define DSM_STBASS_LPF_B2_BYTE0 0x211d +#define DSM_STBASS_LPF_B2_BYTE1 0x211e +#define DSM_STBASS_LPF_B2_BYTE2 0x211f +#define DSM_STBASS_LPF_A1_BYTE0 0x2121 +#define DSM_STBASS_LPF_A1_BYTE1 0x2122 +#define DSM_STBASS_LPF_A1_BYTE2 0x2123 +#define DSM_STBASS_LPF_A2_BYTE0 0x2125 +#define DSM_STBASS_LPF_A2_BYTE1 0x2126 +#define DSM_STBASS_LPF_A2_BYTE2 0x2127 +#define DSM_EQ_BQ1_B0_BYTE0 0x2129 +#define DSM_EQ_BQ1_B0_BYTE1 0x212a +#define DSM_EQ_BQ1_B0_BYTE2 0x212b +#define DSM_EQ_BQ1_B1_BYTE0 0x212d +#define DSM_EQ_BQ1_B1_BYTE1 0x212e +#define DSM_EQ_BQ1_B1_BYTE2 0x212f +#define DSM_EQ_BQ1_B2_BYTE0 0x2131 +#define DSM_EQ_BQ1_B2_BYTE1 0x2132 +#define DSM_EQ_BQ1_B2_BYTE2 0x2133 +#define DSM_EQ_BQ1_A1_BYTE0 0x2135 +#define DSM_EQ_BQ1_A1_BYTE1 0x2136 +#define DSM_EQ_BQ1_A1_BYTE2 0x2137 +#define DSM_EQ_BQ1_A2_BYTE0 0x2139 +#define DSM_EQ_BQ1_A2_BYTE1 0x213a +#define DSM_EQ_BQ1_A2_BYTE2 0x213b +#define DSM_EQ_BQ2_B0_BYTE0 0x213d +#define DSM_EQ_BQ2_B0_BYTE1 0x213e +#define DSM_EQ_BQ2_B0_BYTE2 0x213f +#define DSM_EQ_BQ2_B1_BYTE0 0x2141 +#define DSM_EQ_BQ2_B1_BYTE1 0x2142 +#define DSM_EQ_BQ2_B1_BYTE2 0x2143 +#define DSM_EQ_BQ2_B2_BYTE0 0x2145 +#define DSM_EQ_BQ2_B2_BYTE1 0x2146 +#define DSM_EQ_BQ2_B2_BYTE2 0x2147 +#define DSM_EQ_BQ2_A1_BYTE0 0x2149 +#define DSM_EQ_BQ2_A1_BYTE1 0x214a +#define DSM_EQ_BQ2_A1_BYTE2 0x214b +#define DSM_EQ_BQ2_A2_BYTE0 0x214d +#define DSM_EQ_BQ2_A2_BYTE1 0x214e +#define DSM_EQ_BQ2_A2_BYTE2 0x214f +#define DSM_EQ_BQ3_B0_BYTE0 0x2151 +#define DSM_EQ_BQ3_B0_BYTE1 0x2152 +#define DSM_EQ_BQ3_B0_BYTE2 0x2153 +#define DSM_EQ_BQ3_B1_BYTE0 0x2155 +#define DSM_EQ_BQ3_B1_BYTE1 0x2156 +#define DSM_EQ_BQ3_B1_BYTE2 0x2157 +#define DSM_EQ_BQ3_B2_BYTE0 0x2159 +#define DSM_EQ_BQ3_B2_BYTE1 0x215a +#define DSM_EQ_BQ3_B2_BYTE2 0x215b +#define DSM_EQ_BQ3_A1_BYTE0 0x215d +#define DSM_EQ_BQ3_A1_BYTE1 0x215e +#define DSM_EQ_BQ3_A1_BYTE2 0x215f +#define DSM_EQ_BQ3_A2_BYTE0 0x2161 +#define DSM_EQ_BQ3_A2_BYTE1 0x2162 +#define DSM_EQ_BQ3_A2_BYTE2 0x2163 +#define DSM_EQ_BQ4_B0_BYTE0 0x2165 +#define DSM_EQ_BQ4_B0_BYTE1 0x2166 +#define DSM_EQ_BQ4_B0_BYTE2 0x2167 +#define DSM_EQ_BQ4_B1_BYTE0 0x2169 +#define DSM_EQ_BQ4_B1_BYTE1 0x216a +#define DSM_EQ_BQ4_B1_BYTE2 0x216b +#define DSM_EQ_BQ4_B2_BYTE0 0x216d +#define DSM_EQ_BQ4_B2_BYTE1 0x216e +#define DSM_EQ_BQ4_B2_BYTE2 0x216f +#define DSM_EQ_BQ4_A1_BYTE0 0x2171 +#define DSM_EQ_BQ4_A1_BYTE1 0x2172 +#define DSM_EQ_BQ4_A1_BYTE2 0x2173 +#define DSM_EQ_BQ4_A2_BYTE0 0x2175 +#define DSM_EQ_BQ4_A2_BYTE1 0x2176 +#define DSM_EQ_BQ4_A2_BYTE2 0x2177 +#define DSM_EQ_BQ5_B0_BYTE0 0x2179 +#define DSM_EQ_BQ5_B0_BYTE1 0x217a +#define DSM_EQ_BQ5_B0_BYTE2 0x217b +#define DSM_EQ_BQ5_B1_BYTE0 0x217d +#define DSM_EQ_BQ5_B1_BYTE1 0x217e +#define DSM_EQ_BQ5_B1_BYTE2 0x217f +#define DSM_EQ_BQ5_B2_BYTE0 0x2181 +#define DSM_EQ_BQ5_B2_BYTE1 0x2182 +#define DSM_EQ_BQ5_B2_BYTE2 0x2183 +#define DSM_EQ_BQ5_A1_BYTE0 0x2185 +#define DSM_EQ_BQ5_A1_BYTE1 0x2186 +#define DSM_EQ_BQ5_A1_BYTE2 0x2187 +#define DSM_EQ_BQ5_A2_BYTE0 0x2189 +#define DSM_EQ_BQ5_A2_BYTE1 0x218a +#define DSM_EQ_BQ5_A2_BYTE2 0x218b +#define DSM_EQ_BQ6_B0_BYTE0 0x218d +#define DSM_EQ_BQ6_B0_BYTE1 0x218e +#define DSM_EQ_BQ6_B0_BYTE2 0x218f +#define DSM_EQ_BQ6_B1_BYTE0 0x2191 +#define DSM_EQ_BQ6_B1_BYTE1 0x2192 +#define DSM_EQ_BQ6_B1_BYTE2 0x2193 +#define DSM_EQ_BQ6_B2_BYTE0 0x2195 +#define DSM_EQ_BQ6_B2_BYTE1 0x2196 +#define DSM_EQ_BQ6_B2_BYTE2 0x2197 +#define DSM_EQ_BQ6_A1_BYTE0 0x2199 +#define DSM_EQ_BQ6_A1_BYTE1 0x219a +#define DSM_EQ_BQ6_A1_BYTE2 0x219b +#define DSM_EQ_BQ6_A2_BYTE0 0x219d +#define DSM_EQ_BQ6_A2_BYTE1 0x219e +#define DSM_EQ_BQ6_A2_BYTE2 0x219f +#define DSM_EQ_BQ7_B0_BYTE0 0x21a1 +#define DSM_EQ_BQ7_B0_BYTE1 0x21a2 +#define DSM_EQ_BQ7_B0_BYTE2 0x21a3 +#define DSM_EQ_BQ7_B1_BYTE0 0x21a5 +#define DSM_EQ_BQ7_B1_BYTE1 0x21a6 +#define DSM_EQ_BQ7_B1_BYTE2 0x21a7 +#define DSM_EQ_BQ7_B2_BYTE0 0x21a9 +#define DSM_EQ_BQ7_B2_BYTE1 0x21aa +#define DSM_EQ_BQ7_B2_BYTE2 0x21ab +#define DSM_EQ_BQ7_A1_BYTE0 0x21ad +#define DSM_EQ_BQ7_A1_BYTE1 0x21ae +#define DSM_EQ_BQ7_A1_BYTE2 0x21af +#define DSM_EQ_BQ7_A2_BYTE0 0x21b1 +#define DSM_EQ_BQ7_A2_BYTE1 0x21b2 +#define DSM_EQ_BQ7_A2_BYTE2 0x21b3 +#define DSM_EQ_BQ8_B0_BYTE0 0x21b5 +#define DSM_EQ_BQ8_B0_BYTE1 0x21b6 +#define DSM_EQ_BQ8_B0_BYTE2 0x21b7 +#define DSM_EQ_BQ8_B1_BYTE0 0x21b9 +#define DSM_EQ_BQ8_B1_BYTE1 0x21ba +#define DSM_EQ_BQ8_B1_BYTE2 0x21bb +#define DSM_EQ_BQ8_B2_BYTE0 0x21bd +#define DSM_EQ_BQ8_B2_BYTE1 0x21be +#define DSM_EQ_BQ8_B2_BYTE2 0x21bf +#define DSM_EQ_BQ8_A1_BYTE0 0x21c1 +#define DSM_EQ_BQ8_A1_BYTE1 0x21c2 +#define DSM_EQ_BQ8_A1_BYTE2 0x21c3 +#define DSM_EQ_BQ8_A2_BYTE0 0x21c5 +#define DSM_EQ_BQ8_A2_BYTE1 0x21c6 +#define DSM_EQ_BQ8_A2_BYTE2 0x21c7 +#define DSM_LFX_BQ_B0_BYTE0 0x21c9 +#define DSM_LFX_BQ_B0_BYTE1 0x21ca +#define DSM_LFX_BQ_B0_BYTE2 0x21cb +#define DSM_LFX_BQ_B1_BYTE0 0x21cd +#define DSM_LFX_BQ_B1_BYTE1 0x21ce +#define DSM_LFX_BQ_B1_BYTE2 0x21cf +#define DSM_LFX_BQ_B2_BYTE0 0x21d1 +#define DSM_LFX_BQ_B2_BYTE1 0x21d2 +#define DSM_LFX_BQ_B2_BYTE2 0x21d3 +#define DSM_LFX_BQ_A1_BYTE0 0x21d5 +#define DSM_LFX_BQ_A1_BYTE1 0x21d6 +#define DSM_LFX_BQ_A1_BYTE2 0x21d7 +#define DSM_LFX_BQ_A2_BYTE0 0x21d9 +#define DSM_LFX_BQ_A2_BYTE1 0x21da +#define DSM_LFX_BQ_A2_BYTE2 0x21db +#define DSM_PPR_HPF_B0_BYTE0 0x21dd +#define DSM_PPR_HPF_B0_BYTE1 0x21de +#define DSM_PPR_HPF_B0_BYTE2 0x21df +#define DSM_PPR_HPF_B1_BYTE0 0x21e1 +#define DSM_PPR_HPF_B1_BYTE1 0x21e2 +#define DSM_PPR_HPF_B1_BYTE2 0x21e3 +#define DSM_PPR_HPF_B2_BYTE0 0x21e5 +#define DSM_PPR_HPF_B2_BYTE1 0x21e6 +#define DSM_PPR_HPF_B2_BYTE2 0x21e7 +#define DSM_PPR_HPF_A1_BYTE0 0x21e9 +#define DSM_PPR_HPF_A1_BYTE1 0x21ea +#define DSM_PPR_HPF_A1_BYTE2 0x21eb +#define DSM_PPR_HPF_A2_BYTE0 0x21ed +#define DSM_PPR_HPF_A2_BYTE1 0x21ee +#define DSM_PPR_HPF_A2_BYTE2 0x21ef +#define DSM_PPR_LPF_B0_BYTE0 0x21f1 +#define DSM_PPR_LPF_B0_BYTE1 0x21f2 +#define DSM_PPR_LPF_B0_BYTE2 0x21f3 +#define DSM_PPR_LPF_B1_BYTE0 0x21f5 +#define DSM_PPR_LPF_B1_BYTE1 0x21f6 +#define DSM_PPR_LPF_B1_BYTE2 0x21f7 +#define DSM_PPR_LPF_B2_BYTE0 0x21f9 +#define DSM_PPR_LPF_B2_BYTE1 0x21fa +#define DSM_PPR_LPF_B2_BYTE2 0x21fb +#define DSM_PPR_LPF_A1_BYTE0 0x21fd +#define DSM_PPR_LPF_A1_BYTE1 0x21fe +#define DSM_PPR_LPF_A1_BYTE2 0x21ff +#define DSM_PPR_LPF_A2_BYTE0 0x2201 +#define DSM_PPR_LPF_A2_BYTE1 0x2202 +#define DSM_PPR_LPF_A2_BYTE2 0x2203 +#define DSM_SPL_BQ_B0_BYTE0 0x2205 +#define DSM_SPL_BQ_B0_BYTE1 0x2206 +#define DSM_SPL_BQ_B0_BYTE2 0x2207 +#define DSM_SPL_BQ_B1_BYTE0 0x2209 +#define DSM_SPL_BQ_B1_BYTE1 0x220a +#define DSM_SPL_BQ_B1_BYTE2 0x220b +#define DSM_SPL_BQ_B2_BYTE0 0x220d +#define DSM_SPL_BQ_B2_BYTE1 0x220e +#define DSM_SPL_BQ_B2_BYTE2 0x220f +#define DSM_SPL_BQ_A1_BYTE0 0x2211 +#define DSM_SPL_BQ_A1_BYTE1 0x2212 +#define DSM_SPL_BQ_A1_BYTE2 0x2213 +#define DSM_SPL_BQ_A2_BYTE0 0x2215 +#define DSM_SPL_BQ_A2_BYTE1 0x2216 +#define DSM_SPL_BQ_A2_BYTE2 0x2217 +#define DSM_EXCUR_BQ_B0_BYTE0 0x2219 +#define DSM_EXCUR_BQ_B0_BYTE1 0x221a +#define DSM_EXCUR_BQ_B0_BYTE2 0x221b +#define DSM_EXCUR_BQ_B1_BYTE0 0x221d +#define DSM_EXCUR_BQ_B1_BYTE1 0x221e +#define DSM_EXCUR_BQ_B1_BYTE2 0x221f +#define DSM_EXCUR_BQ_B2_BYTE0 0x2221 +#define DSM_EXCUR_BQ_B2_BYTE1 0x2222 +#define DSM_EXCUR_BQ_B2_BYTE2 0x2223 +#define DSM_EXCUR_BQ_A1_BYTE0 0x2225 +#define DSM_EXCUR_BQ_A1_BYTE1 0x2226 +#define DSM_EXCUR_BQ_A1_BYTE2 0x2227 +#define DSM_EXCUR_BQ_A2_BYTE0 0x2229 +#define DSM_EXCUR_BQ_A2_BYTE1 0x222a +#define DSM_EXCUR_BQ_A2_BYTE2 0x222b +#define DSM_EXCPROT_HPF1_B0_BYTE0 0x222d +#define DSM_EXCPROT_HPF1_B0_BYTE1 0x222e +#define DSM_EXCPROT_HPF1_B0_BYTE2 0x222f +#define DSM_EXCPROT_HPF1_B1_BYTE0 0x2231 +#define DSM_EXCPROT_HPF1_B1_BYTE1 0x2232 +#define DSM_EXCPROT_HPF1_B1_BYTE2 0x2233 +#define DSM_EXCPROT_HPF1_B2_BYTE0 0x2235 +#define DSM_EXCPROT_HPF1_B2_BYTE1 0x2236 +#define DSM_EXCPROT_HPF1_B2_BYTE2 0x2237 +#define DSM_EXCPROT_HPF1_A1_BYTE0 0x2239 +#define DSM_EXCPROT_HPF1_A1_BYTE1 0x223a +#define DSM_EXCPROT_HPF1_A1_BYTE2 0x223b +#define DSM_EXCPROT_HPF1_A2_BYTE0 0x223d +#define DSM_EXCPROT_HPF1_A2_BYTE1 0x223e +#define DSM_EXCPROT_HPF1_A2_BYTE2 0x223f +#define DSM_EXCPROT_HPF2_B0_BYTE0 0x2241 +#define DSM_EXCPROT_HPF2_B0_BYTE1 0x2242 +#define DSM_EXCPROT_HPF2_B0_BYTE2 0x2243 +#define DSM_EXCPROT_HPF2_B1_BYTE0 0x2245 +#define DSM_EXCPROT_HPF2_B1_BYTE1 0x2246 +#define DSM_EXCPROT_HPF2_B1_BYTE2 0x2247 +#define DSM_EXCPROT_HPF2_B2_BYTE0 0x2249 +#define DSM_EXCPROT_HPF2_B2_BYTE1 0x224a +#define DSM_EXCPROT_HPF2_B2_BYTE2 0x224b +#define DSM_EXCPROT_HPF2_A1_BYTE0 0x224d +#define DSM_EXCPROT_HPF2_A1_BYTE1 0x224e +#define DSM_EXCPROT_HPF2_A1_BYTE2 0x224f +#define DSM_EXCPROT_HPF2_A2_BYTE0 0x2251 +#define DSM_EXCPROT_HPF2_A2_BYTE1 0x2252 +#define DSM_EXCPROT_HPF2_A2_BYTE2 0x2253 +#define DSM_EXCPROT_HPF3_B0_BYTE0 0x2255 +#define DSM_EXCPROT_HPF3_B0_BYTE1 0x2256 +#define DSM_EXCPROT_HPF3_B0_BYTE2 0x2257 +#define DSM_EXCPROT_HPF3_B1_BYTE0 0x2259 +#define DSM_EXCPROT_HPF3_B1_BYTE1 0x225a +#define DSM_EXCPROT_HPF3_B1_BYTE2 0x225b +#define DSM_EXCPROT_HPF3_B2_BYTE0 0x225d +#define DSM_EXCPROT_HPF3_B2_BYTE1 0x225e +#define DSM_EXCPROT_HPF3_B2_BYTE2 0x225f +#define DSM_EXCPROT_HPF3_A1_BYTE0 0x2261 +#define DSM_EXCPROT_HPF3_A1_BYTE1 0x2262 +#define DSM_EXCPROT_HPF3_A1_BYTE2 0x2263 +#define DSM_EXCPROT_HPF3_A2_BYTE0 0x2265 +#define DSM_EXCPROT_HPF3_A2_BYTE1 0x2266 +#define DSM_EXCPROT_HPF3_A2_BYTE2 0x2267 +#define DSM_EXCPROT_HPF4_B0_BYTE0 0x2269 +#define DSM_EXCPROT_HPF4_B0_BYTE1 0x226a +#define DSM_EXCPROT_HPF4_B0_BYTE2 0x226b +#define DSM_EXCPROT_HPF4_B1_BYTE0 0x226d +#define DSM_EXCPROT_HPF4_B1_BYTE1 0x226e +#define DSM_EXCPROT_HPF4_B1_BYTE2 0x226f +#define DSM_EXCPROT_HPF4_B2_BYTE0 0x2271 +#define DSM_EXCPROT_HPF4_B2_BYTE1 0x2272 +#define DSM_EXCPROT_HPF4_B2_BYTE2 0x2273 +#define DSM_EXCPROT_HPF4_A1_BYTE0 0x2275 +#define DSM_EXCPROT_HPF4_A1_BYTE1 0x2276 +#define DSM_EXCPROT_HPF4_A1_BYTE2 0x2277 +#define DSM_EXCPROT_HPF4_A2_BYTE0 0x2279 +#define DSM_EXCPROT_HPF4_A2_BYTE1 0x227a +#define DSM_EXCPROT_HPF4_A2_BYTE2 0x227b +#define DSM_EXCPROT_HPF5_B0_BYTE0 0x227d +#define DSM_EXCPROT_HPF5_B0_BYTE1 0x227e +#define DSM_EXCPROT_HPF5_B0_BYTE2 0x227f +#define DSM_EXCPROT_HPF5_B1_BYTE0 0x2281 +#define DSM_EXCPROT_HPF5_B1_BYTE1 0x2282 +#define DSM_EXCPROT_HPF5_B1_BYTE2 0x2283 +#define DSM_EXCPROT_HPF5_B2_BYTE0 0x2285 +#define DSM_EXCPROT_HPF5_B2_BYTE1 0x2286 +#define DSM_EXCPROT_HPF5_B2_BYTE2 0x2287 +#define DSM_EXCPROT_HPF5_A1_BYTE0 0x2289 +#define DSM_EXCPROT_HPF5_A1_BYTE1 0x228a +#define DSM_EXCPROT_HPF5_A1_BYTE2 0x228b +#define DSM_EXCPROT_HPF5_A2_BYTE0 0x228d +#define DSM_EXCPROT_HPF5_A2_BYTE1 0x228e +#define DSM_EXCPROT_HPF5_A2_BYTE2 0x228f +#define DSM_DEBUZZ_BPF_B0_BYTE0 0x2291 +#define DSM_DEBUZZ_BPF_B0_BYTE1 0x2292 +#define DSM_DEBUZZ_BPF_B0_BYTE2 0x2293 +#define DSM_DEBUZZ_BPF_B1_BYTE0 0x2295 +#define DSM_DEBUZZ_BPF_B1_BYTE1 0x2296 +#define DSM_DEBUZZ_BPF_B1_BYTE2 0x2297 +#define DSM_DEBUZZ_BPF_B2_BYTE0 0x2299 +#define DSM_DEBUZZ_BPF_B2_BYTE1 0x229a +#define DSM_DEBUZZ_BPF_B2_BYTE2 0x229b +#define DSM_DEBUZZ_BPF_A1_BYTE0 0x229d +#define DSM_DEBUZZ_BPF_A1_BYTE1 0x229e +#define DSM_DEBUZZ_BPF_A1_BYTE2 0x229f +#define DSM_DEBUZZ_BPF_A2_BYTE0 0x22a1 +#define DSM_DEBUZZ_BPF_A2_BYTE1 0x22a2 +#define DSM_DEBUZZ_BPF_A2_BYTE2 0x22a3 +#define DSM_DEBUZZ_PORT_B0_BYTE0 0x22a5 +#define DSM_DEBUZZ_PORT_B0_BYTE1 0x22a6 +#define DSM_DEBUZZ_PORT_B0_BYTE2 0x22a7 +#define DSM_DEBUZZ_PORT_B1_BYTE0 0x22a9 +#define DSM_DEBUZZ_PORT_B1_BYTE1 0x22aa +#define DSM_DEBUZZ_PORT_B1_BYTE2 0x22ab +#define DSM_DEBUZZ_PORT_B2_BYTE0 0x22ad +#define DSM_DEBUZZ_PORT_B2_BYTE1 0x22ae +#define DSM_DEBUZZ_PORT_B2_BYTE2 0x22af +#define DSM_DEBUZZ_PORT_A1_BYTE0 0x22b1 +#define DSM_DEBUZZ_PORT_A1_BYTE1 0x22b2 +#define DSM_DEBUZZ_PORT_A1_BYTE2 0x22b3 +#define DSM_DEBUZZ_PORT_A2_BYTE0 0x22b5 +#define DSM_DEBUZZ_PORT_A2_BYTE1 0x22b6 +#define DSM_DEBUZZ_PORT_A2_BYTE2 0x22b7 +#define DSM_DEBUZZ_NOTCH_B0_BYTE0 0x22b9 +#define DSM_DEBUZZ_NOTCH_B0_BYTE1 0x22ba +#define DSM_DEBUZZ_NOTCH_B0_BYTE2 0x22bb +#define DSM_DEBUZZ_NOTCH_B1_BYTE0 0x22bd +#define DSM_DEBUZZ_NOTCH_B1_BYTE1 0x22be +#define DSM_DEBUZZ_NOTCH_B1_BYTE2 0x22bf +#define DSM_DEBUZZ_NOTCH_B2_BYTE0 0x22c1 +#define DSM_DEBUZZ_NOTCH_B2_BYTE1 0x22c2 +#define DSM_DEBUZZ_NOTCH_B2_BYTE2 0x22c3 +#define DSM_DEBUZZ_NOTCH_A1_BYTE0 0x22c5 +#define DSM_DEBUZZ_NOTCH_A1_BYTE1 0x22c6 +#define DSM_DEBUZZ_NOTCH_A1_BYTE2 0x22c7 +#define DSM_DEBUZZ_NOTCH_A2_BYTE0 0x22c9 +#define DSM_DEBUZZ_NOTCH_A2_BYTE1 0x22ca +#define DSM_DEBUZZ_NOTCH_A2_BYTE2 0x22cb +#define DSM_THERMAL_BQ_B0_BYTE0 0x22cd +#define DSM_THERMAL_BQ_B0_BYTE1 0x22ce +#define DSM_THERMAL_BQ_B0_BYTE2 0x22cf +#define DSM_THERMAL_BQ_B1_BYTE0 0x22d1 +#define DSM_THERMAL_BQ_B1_BYTE1 0x22d2 +#define DSM_THERMAL_BQ_B1_BYTE2 0x22d3 +#define DSM_THERMAL_BQ_B2_BYTE0 0x22d5 +#define DSM_THERMAL_BQ_B2_BYTE1 0x22d6 +#define DSM_THERMAL_BQ_B2_BYTE2 0x22d7 +#define DSM_THERMAL_BQ_A1_BYTE0 0x22d9 +#define DSM_THERMAL_BQ_A1_BYTE1 0x22da +#define DSM_THERMAL_BQ_A1_BYTE2 0x22db +#define DSM_THERMAL_BQ_A2_BYTE0 0x22dd +#define DSM_THERMAL_BQ_A2_BYTE1 0x22de +#define DSM_THERMAL_BQ_A2_BYTE2 0x22df +#define DSM_WBDRC_FILT1_B0_BYTE0 0x22e1 +#define DSM_WBDRC_FILT1_B0_BYTE1 0x22e2 +#define DSM_WBDRC_FILT1_B0_BYTE2 0x22e3 +#define DSM_WBDRC_FILT1_B1_BYTE0 0x22e5 +#define DSM_WBDRC_FILT1_B1_BYTE1 0x22e6 +#define DSM_WBDRC_FILT1_B1_BYTE2 0x22e7 +#define DSM_WBDRC_FILT1_B2_BYTE0 0x22e9 +#define DSM_WBDRC_FILT1_B2_BYTE1 0x22ea +#define DSM_WBDRC_FILT1_B2_BYTE2 0x22eb +#define DSM_WBDRC_FILT1_A1_BYTE0 0x22ed +#define DSM_WBDRC_FILT1_A1_BYTE1 0x22ee +#define DSM_WBDRC_FILT1_A1_BYTE2 0x22ef +#define DSM_WBDRC_FILT1_A2_BYTE0 0x22f1 +#define DSM_WBDRC_FILT1_A2_BYTE1 0x22f2 +#define DSM_WBDRC_FILT1_A2_BYTE2 0x22f3 +#define DSM_WBDRC_FILT2_B0_BYTE0 0x22f5 +#define DSM_WBDRC_FILT2_B0_BYTE1 0x22f6 +#define DSM_WBDRC_FILT2_B0_BYTE2 0x22f7 +#define DSM_WBDRC_FILT2_B1_BYTE0 0x22f9 +#define DSM_WBDRC_FILT2_B1_BYTE1 0x22fa +#define DSM_WBDRC_FILT2_B1_BYTE2 0x22fb +#define DSM_WBDRC_FILT2_B2_BYTE0 0x22fd +#define DSM_WBDRC_FILT2_B2_BYTE1 0x22fe +#define DSM_WBDRC_FILT2_B2_BYTE2 0x22ff +#define DSM_WBDRC_FILT2_A1_BYTE0 0x2301 +#define DSM_WBDRC_FILT2_A1_BYTE1 0x2302 +#define DSM_WBDRC_FILT2_A1_BYTE2 0x2303 +#define DSM_WBDRC_FILT2_A2_BYTE0 0x2305 +#define DSM_WBDRC_FILT2_A2_BYTE1 0x2306 +#define DSM_WBDRC_FILT2_A2_BYTE2 0x2307 +#define DSM_PPR_RELEASE_TIME_BYTE0 0x2309 +#define DSM_PPR_RELEASE_TIME_BYTE1 0x230a +#define DSM_PPR_RELEASE_TIME_BYTE2 0x230b +#define DSM_PPR_ATTACK_TIME_BYTE0 0x230d +#define DSM_PPR_ATTACK_TIME_BYTE1 0x230e +#define DSM_PPR_ATTACK_TIME_BYTE2 0x230f +#define DSM_DEBUZZER_RELEASE_TIME_BYTE0 0x2311 +#define DSM_DEBUZZER_RELEASE_TIME_BYTE1 0x2312 +#define DSM_DEBUZZER_RELEASE_TIME_BYTE2 0x2313 +#define DSM_DEBUZZER_ATTACK_TIME_BYTE0 0x2315 +#define DSM_DEBUZZER_ATTACK_TIME_BYTE1 0x2316 +#define DSM_DEBUZZER_ATTACK_TIME_BYTE2 0x2317 + +#define DSMIG_WB_DRC_RELEASE_TIME_1 0x2380 +#define DSMIG_WB_DRC_RELEASE_TIME_2 0x2381 +#define DSMIG_WB_DRC_ATTACK_TIME_1 0x2382 +#define DSMIG_WB_DRC_ATTACK_TIME_2 0x2383 +#define DSMIG_WB_DRC_COMPRESSION_RATIO 0x2384 +#define DSMIG_WB_DRC_COMPRESSION_THRESHOLD 0x2385 +#define DSMIG_WB_DRC_MAKEUPGAIN 0x2386 +#define DSMIG_WB_DRC_NOISE_GATE_THRESHOLD 0x2387 +#define DSMIG_WBDRC_HPF_ENABLE 0x2388 +#define DSMIG_WB_DRC_TEST_SMOOTHER_OUT_EN 0x2389 +#define DSMIG_PPR_THRESHOLD 0x238b +#define DSM_STEREO_BASS_CHANNEL_SELECT 0x238d +#define DSM_TPROT_THRESHOLD_BYTE0 0x238e +#define DSM_TPROT_THRESHOLD_BYTE1 0x238f +#define DSM_TPROT_ROOM_TEMPERATURE_BYTE0 0x2390 +#define DSM_TPROT_ROOM_TEMPERATURE_BYTE1 0x2391 +#define DSM_TPROT_RECIP_RDC_ROOM_BYTE0 0x2392 +#define DSM_TPROT_RECIP_RDC_ROOM_BYTE1 0x2393 +#define DSM_TPROT_RECIP_RDC_ROOM_BYTE2 0x2394 +#define DSM_TPROT_RECIP_TCONST_BYTE0 0x2395 +#define DSM_TPROT_RECIP_TCONST_BYTE1 0x2396 +#define DSM_TPROT_RECIP_TCONST_BYTE2 0x2397 +#define DSM_THERMAL_ATTENUATION_SETTINGS 0x2398 +#define DSM_THERMAL_PILOT_TONE_ATTENUATION 0x2399 +#define DSM_TPROT_PG_TEMP_THRESH_BYTE0 0x239a +#define DSM_TPROT_PG_TEMP_THRESH_BYTE1 0x239b + +#define THERMAL_RDC_RD_BACK_BYTE1 0x239c +#define THERMAL_RDC_RD_BACK_BYTE0 0x239d +#define THERMAL_COILTEMP_RD_BACK_BYTE1 0x239e +#define THERMAL_COILTEMP_RD_BACK_BYTE0 0x239f + +#define DSMIG_DEBUZZER_THRESHOLD 0x23b5 +#define DSMIG_DEBUZZER_ALPHA_COEF_TEST_ONLY 0x23b6 +#define DSM_VOL_ENA 0x23b9 +#define DSM_VOL_CTRL 0x23ba + +#define DSMIG_EN 0x23e0 +#define MAX98390_R23E1_DSP_GLOBAL_EN 0x23e1 + +#define DSM_THERMAL_GAIN 0x23f0 +#define DSM_PPR_GAIN 0x23f1 +#define DSM_DBZ_GAIN 0x23f2 +#define DSM_WBDRC_GAIN 0x23f3 + +#define MAX98390_R23FF_GLOBAL_EN 0x23FF +#define MAX98390_R24FF_REV_ID 0x24FF + +/* MAX98390_R2021_PCM_RX_SRC_1 */ +#define MAX98390_PCM_RX_CH_SRC_SHIFT (0) +#define MAX98390_PCM_RX_CH_SRC_BASS_SHIFT (4) + +/* MAX98390_R2022_PCM_TX_SRC_1 */ +#define MAX98390_PCM_TX_CH_SRC_A_V_SHIFT (0) +#define MAX98390_PCM_TX_CH_SRC_A_I_SHIFT (4) + +/* MAX98390_R2024_PCM_DATA_FMT_CFG */ +#define MAX98390_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3) +#define MAX98390_PCM_MODE_CFG_FORMAT_SHIFT (3) +#define MAX98390_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 2) +#define MAX98390_PCM_FORMAT_I2S (0x0 << 0) +#define MAX98390_PCM_FORMAT_LJ (0x1 << 0) +#define MAX98390_PCM_FORMAT_TDM_MODE0 (0x3 << 0) +#define MAX98390_PCM_FORMAT_TDM_MODE1 (0x4 << 0) +#define MAX98390_PCM_FORMAT_TDM_MODE2 (0x5 << 0) +#define MAX98390_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6) +#define MAX98390_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6) +#define MAX98390_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6) +#define MAX98390_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6) + +/* MAX98390_R2039_AMP_DSP_CFG */ +#define MAX98390_AMP_DSP_CFG_RMP_UP_SHIFT (4) +#define MAX98390_AMP_DSP_CFG_RMP_DN_SHIFT (5) + +/* MAX98390_R203A_AMP_EN */ +#define MAX98390_R203A_AMP_EN_SHIFT (0) + +/* MAX98390_PCM_MASTER_MODE */ +#define MAX98390_PCM_MASTER_MODE_MASK (0x3 << 0) +#define MAX98390_PCM_MASTER_MODE_SLAVE (0x0 << 0) +#define MAX98390_PCM_MASTER_MODE_MASTER (0x3 << 0) + +#define MAX98390_PCM_MASTER_MODE_MCLK_MASK (0xF << 2) +#define MAX98390_PCM_MASTER_MODE_MCLK_RATE_SHIFT (2) + +/* PCM_CLK_SETUP */ +#define MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 2) +#define MAX98390_PCM_CLK_SETUP_BSEL_MASK (0xF << 0) + +/* PCM_SR_SETUP */ +#define MAX98390_PCM_SR_SET1_SR_MASK (0xF << 0) +#define MAX98390_PCM_SR_SET1_SR_8000 (0x0 << 0) +#define MAX98390_PCM_SR_SET1_SR_11025 (0x1 << 0) +#define MAX98390_PCM_SR_SET1_SR_12000 (0x2 << 0) +#define MAX98390_PCM_SR_SET1_SR_16000 (0x3 << 0) +#define MAX98390_PCM_SR_SET1_SR_22050 (0x4 << 0) +#define MAX98390_PCM_SR_SET1_SR_24000 (0x5 << 0) +#define MAX98390_PCM_SR_SET1_SR_32000 (0x6 << 0) +#define MAX98390_PCM_SR_SET1_SR_44100 (0x7 << 0) +#define MAX98390_PCM_SR_SET1_SR_48000 (0x8 << 0) + +/* PCM_TO_SPK_MONO_MIX_1 */ +#define MAX98390_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6) +#define MAX98390_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6) +#define MAX98390_PCM_TO_SPK_CH0_SRC_MASK (0xF << 0) +#define MAX98390_PCM_TO_SPK_CH1_SRC_MASK (0xF << 4) + +/* MAX98390_BOOST_CTRL3 */ +#define MAX98390_BOOST_CLK_PHASE_CFG_SHIFT (2) + +/* SOFT_RESET */ +#define MAX98390_SOFT_RESET_MASK (0x1 << 0) + +#define MAX98390_GLOBAL_EN_MASK (0x1 << 0) +#define MAX98390_AMP_EN_MASK (0x1 << 0) + +/* DSM register offset */ +#define MAX98390_DSM_PAYLOAD_OFFSET 16 +#define MAX98390_DSM_PAYLOAD_OFFSET_2 495 + +struct max98390_priv { + struct regmap *regmap; + unsigned int sysclk; + unsigned int master; + unsigned int tdm_mode; + unsigned int ref_rdc_value; + unsigned int ambient_temp_value; +}; +#endif From cff1f8b4f8e119a9dbd9872d7a04fedef8d0c1a2 Mon Sep 17 00:00:00 2001 From: shengjiu wang Date: Mon, 25 May 2020 17:03:32 +0800 Subject: [PATCH 362/428] ASoC: fsl_asrc: Fix -Wmissing-prototypes warning COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 sound/soc/fsl/fsl_asrc.c:557:18: warning: no previous prototype for function 'fsl_asrc_get_dma_channel' [-Wmissing-prototypes] struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) ^ sound/soc/fsl/fsl_asrc.c:557:1: note: declare 'static' if the function is not intended to be used outside of this translation unit struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) ^ static Fixes: be7bd03f0201 ("ASoC: fsl_asrc: Move common definition to fsl_asrc_common") Reported-by: kbuild test robot Signed-off-by: shengjiu wang Link: https://lore.kernel.org/r/1590397412-12966-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 7e2d598ffb81..d79d2c7f8d36 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -554,7 +554,8 @@ static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) /** * Get DMA channel according to the pair and direction. */ -struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) +static struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, + bool dir) { struct fsl_asrc *asrc = pair->asrc; enum asrc_pair_index index = pair->index; @@ -564,7 +565,6 @@ struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) return dma_request_slave_channel(&asrc->pdev->dev, name); } -EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel); static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) From 085c02d355ac585184ef4f00eb333cd86f6add80 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Wed, 13 May 2020 19:14:08 +0800 Subject: [PATCH 363/428] ASoC: fsl: imx-audmix: Fix unused assignment to variable 'ret' Omit unused initialized value, because 'ret' will be assigined by the function snd_soc_component_read(). Signed-off-by: Zhang Shengju Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200513111408.11452-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 5faecbeb5497..8b9027f76d8a 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -116,7 +116,7 @@ static int fsl_audmix_put_mix_clk_src(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int *item = ucontrol->value.enumerated.item; unsigned int reg_val, val, mix_clk; - int ret = 0; + int ret; /* Get current state */ ret = snd_soc_component_read(comp, FSL_AUDMIX_CTR, ®_val); @@ -159,7 +159,7 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol, unsigned int *item = ucontrol->value.enumerated.item; u32 out_src, mix_clk; unsigned int reg_val, val, mask = 0, ctr = 0; - int ret = 0; + int ret; /* Get current state */ ret = snd_soc_component_read(comp, FSL_AUDMIX_CTR, ®_val); From 393dc21d0f25e8fcde8baca78b8a38afe61db2a7 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 22 May 2020 17:57:24 +0800 Subject: [PATCH 364/428] ASoC: fsl_asrc: Merge suspend/resume function to runtime_suspend/resume With dedicated power domain for asrc, power can be disabled after probe and pm runtime suspend, then the value of all registers need to be restored in pm runtime resume. So we can merge suspend/resume function to runtime_suspend/resume function and enable regcache only in end of probe. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/1590141444-28668-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 70 ++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 43 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index d79d2c7f8d36..95f6a9617b0b 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1105,6 +1105,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, asrc); pm_runtime_enable(&pdev->dev); spin_lock_init(&asrc->lock); + regcache_cache_only(asrc->regmap, true); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component, &fsl_asrc_dai, 1); @@ -1122,6 +1123,7 @@ static int fsl_asrc_runtime_resume(struct device *dev) struct fsl_asrc *asrc = dev_get_drvdata(dev); struct fsl_asrc_priv *asrc_priv = asrc->private; int i, ret; + u32 asrctr; ret = clk_prepare_enable(asrc->mem_clk); if (ret) @@ -1140,6 +1142,24 @@ static int fsl_asrc_runtime_resume(struct device *dev) goto disable_asrck_clk; } + /* Stop all pairs provisionally */ + regmap_read(asrc->regmap, REG_ASRCTR, &asrctr); + regmap_update_bits(asrc->regmap, REG_ASRCTR, + ASRCTR_ASRCEi_ALL_MASK, 0); + + /* Restore all registers */ + regcache_cache_only(asrc->regmap, false); + regcache_mark_dirty(asrc->regmap); + regcache_sync(asrc->regmap); + + regmap_update_bits(asrc->regmap, REG_ASRCFG, + ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK | + ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg); + + /* Restart enabled pairs */ + regmap_update_bits(asrc->regmap, REG_ASRCTR, + ASRCTR_ASRCEi_ALL_MASK, asrctr); + return 0; disable_asrck_clk: @@ -1160,6 +1180,11 @@ static int fsl_asrc_runtime_suspend(struct device *dev) struct fsl_asrc_priv *asrc_priv = asrc->private; int i; + regmap_read(asrc->regmap, REG_ASRCFG, + &asrc_priv->regcache_cfg); + + regcache_cache_only(asrc->regmap, true); + for (i = 0; i < ASRC_CLK_MAX_NUM; i++) clk_disable_unprepare(asrc_priv->asrck_clk[i]); if (!IS_ERR(asrc->spba_clk)) @@ -1171,51 +1196,10 @@ static int fsl_asrc_runtime_suspend(struct device *dev) } #endif /* CONFIG_PM */ -#ifdef CONFIG_PM_SLEEP -static int fsl_asrc_suspend(struct device *dev) -{ - struct fsl_asrc *asrc = dev_get_drvdata(dev); - struct fsl_asrc_priv *asrc_priv = asrc->private; - - regmap_read(asrc->regmap, REG_ASRCFG, - &asrc_priv->regcache_cfg); - - regcache_cache_only(asrc->regmap, true); - regcache_mark_dirty(asrc->regmap); - - return 0; -} - -static int fsl_asrc_resume(struct device *dev) -{ - struct fsl_asrc *asrc = dev_get_drvdata(dev); - struct fsl_asrc_priv *asrc_priv = asrc->private; - u32 asrctr; - - /* Stop all pairs provisionally */ - regmap_read(asrc->regmap, REG_ASRCTR, &asrctr); - regmap_update_bits(asrc->regmap, REG_ASRCTR, - ASRCTR_ASRCEi_ALL_MASK, 0); - - /* Restore all registers */ - regcache_cache_only(asrc->regmap, false); - regcache_sync(asrc->regmap); - - regmap_update_bits(asrc->regmap, REG_ASRCFG, - ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK | - ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg); - - /* Restart enabled pairs */ - regmap_update_bits(asrc->regmap, REG_ASRCTR, - ASRCTR_ASRCEi_ALL_MASK, asrctr); - - return 0; -} -#endif /* CONFIG_PM_SLEEP */ - static const struct dev_pm_ops fsl_asrc_pm = { SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static const struct fsl_asrc_soc_data fsl_asrc_imx35_data = { From edc475bee00b18f6de16ce3e6da8fdec8b476302 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Tue, 26 May 2020 02:43:51 +0800 Subject: [PATCH 365/428] ASoC: fix semicolon.cocci warnings sound/soc/codecs/zl38060.c:298:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Fixes: 52e8a94baf90 ("ASoC: Add initial ZL38060 driver") Signed-off-by: kbuild test robot CC: Sven Van Asbroeck Link: https://lore.kernel.org/r/20200525184351.GA37386@5cf39b9a5cc3 Signed-off-by: Mark Brown --- sound/soc/codecs/zl38060.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/zl38060.c b/sound/soc/codecs/zl38060.c index 927ad849ad2d..42726dc0ba39 100644 --- a/sound/soc/codecs/zl38060.c +++ b/sound/soc/codecs/zl38060.c @@ -295,7 +295,7 @@ static int zl38_hw_params(struct snd_pcm_substream *substream, break; default: return -EINVAL; - }; + } err = regmap_update_bits(priv->regmap, REG_TDMA_CFG_CLK, CFG_CLK_FSRATE_MASK, fsrate); From c553d290577093553098a56c954e516950c35c59 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Mon, 25 May 2020 16:58:48 +0800 Subject: [PATCH 366/428] ASoC: ti: Fix runtime PM imbalance in omap2_mcbsp_set_clks_src When clk_set_parent() returns an error code, a pairing runtime PM usage counter increment is needed to keep the counter balanced. Signed-off-by: Dinghao Liu Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200525085848.4227-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- sound/soc/ti/omap-mcbsp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 4e67769b795a..32e3ccdbb7a2 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -77,18 +77,15 @@ static int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) pm_runtime_put_sync(mcbsp->dev); r = clk_set_parent(mcbsp->fclk, fck_src); - if (r) { + if (r) dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n", src); - clk_put(fck_src); - return r; - } pm_runtime_get_sync(mcbsp->dev); clk_put(fck_src); - return 0; + return r; } static irqreturn_t omap_mcbsp_irq_handler(int irq, void *data) From 25bf943e4e7b47282bd86ae7d39e039217ebb007 Mon Sep 17 00:00:00 2001 From: Qiushi Wu Date: Mon, 25 May 2020 00:50:11 -0500 Subject: [PATCH 367/428] ASoC: fix incomplete error-handling in img_i2s_in_probe. Function "pm_runtime_get_sync()" is not handled by "pm_runtime_put()" if "PTR_ERR(rst) == -EPROBE_DEFER". Fix this issue by adding "pm_runtime_put()" into this error path. Fixes: f65bb92ca12e ("ASoC: img-i2s-in: Add runtime PM") Signed-off-by: Qiushi Wu Link: https://lore.kernel.org/r/20200525055011.31925-1-wu000273@umn.edu Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-in.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index a495d1050d49..e30b66b94bf6 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -482,6 +482,7 @@ static int img_i2s_in_probe(struct platform_device *pdev) if (IS_ERR(rst)) { if (PTR_ERR(rst) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; + pm_runtime_put(&pdev->dev); goto err_suspend; } From 0d71a5cf691a8226151ceeb79fb872925f053df5 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Mon, 25 May 2020 15:17:30 +0800 Subject: [PATCH 368/428] ASoC: tas2552: Fix runtime PM imbalance in tas2552_component_probe pm_runtime_get_sync() increments the runtime PM usage counter even when it returns an error code. Thus a pairing decrement is needed on the error handling path to keep the counter balanced. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20200525071732.5887-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- sound/soc/codecs/tas2552.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 56671f21cfe5..d90e5f2b6f27 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -602,6 +602,7 @@ static int tas2552_component_probe(struct snd_soc_component *component) return 0; probe_fail: + pm_runtime_put_noidle(component->dev); gpiod_set_value(tas2552->enable_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies), From f4aa5e214eeaf7f1c7f157526a5aa29784cb6a1f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 May 2020 17:19:30 +0100 Subject: [PATCH 369/428] ASoC: dapm: Move dai_link widgets to runtime to fix use after free The newly added CODEC to CODEC DAI link widget pointers in snd_soc_dai_link are better placed in snd_soc_pcm_runtime. snd_soc_dai_link is really intended for static configuration of the DAI, and the runtime for dynamic data. The snd_soc_dai_link structures are not destroyed if the card is unbound. The widgets are cleared up on unbind, however if the card is rebound as the snd_soc_dai_link structures are reused these pointers will be left at their old values, causing access to freed memory. Fixes: 595571cca4de ("ASoC: dapm: Fix regression introducing multiple copies of DAI widgets") Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20200526161930.30759-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc.h | 6 +++--- sound/soc/soc-dapm.c | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 946f88a6c63d..53e2062b9cef 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -790,9 +790,6 @@ struct snd_soc_dai_link { const struct snd_soc_pcm_stream *params; unsigned int num_params; - struct snd_soc_dapm_widget *playback_widget; - struct snd_soc_dapm_widget *capture_widget; - unsigned int dai_fmt; /* format to set on init */ enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */ @@ -1156,6 +1153,9 @@ struct snd_soc_pcm_runtime { struct snd_soc_dai **cpu_dais; unsigned int num_cpus; + struct snd_soc_dapm_widget *playback_widget; + struct snd_soc_dapm_widget *capture_widget; + struct delayed_work delayed_work; void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd); #ifdef CONFIG_DEBUG_FS diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index e2632841b321..c0aa64ff8e32 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4340,16 +4340,16 @@ static void dapm_connect_dai_pair(struct snd_soc_card *card, codec = codec_dai->playback_widget; if (playback_cpu && codec) { - if (dai_link->params && !dai_link->playback_widget) { + if (dai_link->params && !rtd->playback_widget) { substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream; dai = snd_soc_dapm_new_dai(card, substream, "playback"); if (IS_ERR(dai)) goto capture; - dai_link->playback_widget = dai; + rtd->playback_widget = dai; } dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu, - dai_link->playback_widget, + rtd->playback_widget, codec_dai, codec); } @@ -4358,16 +4358,16 @@ capture: codec = codec_dai->capture_widget; if (codec && capture_cpu) { - if (dai_link->params && !dai_link->capture_widget) { + if (dai_link->params && !rtd->capture_widget) { substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream; dai = snd_soc_dapm_new_dai(card, substream, "capture"); if (IS_ERR(dai)) return; - dai_link->capture_widget = dai; + rtd->capture_widget = dai; } dapm_connect_dai_routes(&card->dapm, codec_dai, codec, - dai_link->capture_widget, + rtd->capture_widget, cpu_dai, capture_cpu); } } From ddcccd543f5dbd841fe305452651b0f8c1d74f0f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 26 May 2020 15:36:33 -0500 Subject: [PATCH 370/428] ASoC: SOF: Intel: byt: Add PM callbacks Add the PM callbacks for BYT/CHT platforms. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Tested-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20200526203640.25980-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 3747f2c2c28b..457da8fcc6a0 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -428,6 +428,34 @@ static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach, mach_params->platform = dev_name(dev); } +static void byt_reset_dsp_disable_int(struct snd_sof_dev *sdev) +{ + /* Disable Interrupt from both sides */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x3); + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x3); + + /* Put DSP into reset, set reset vector */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR, + SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL, + SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL); +} + +static int byt_suspend(struct snd_sof_dev *sdev, u32 target_state) +{ + byt_reset_dsp_disable_int(sdev); + + return 0; +} + +static int byt_resume(struct snd_sof_dev *sdev) +{ + /* Enable Interrupt from both sides */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + + return 0; +} + /* Baytrail DAIs */ static struct snd_soc_dai_driver byt_dai[] = { { @@ -832,6 +860,10 @@ const struct snd_sof_dsp_ops sof_byt_ops = { /*Firmware loading */ .load_firmware = snd_sof_load_firmware_memcpy, + /* PM */ + .suspend = byt_suspend, + .resume = byt_resume, + /* DAI drivers */ .drv = byt_dai, .num_drv = 3, /* we have only 3 SSPs on byt*/ @@ -906,6 +938,10 @@ const struct snd_sof_dsp_ops sof_cht_ops = { /*Firmware loading */ .load_firmware = snd_sof_load_firmware_memcpy, + /* PM */ + .suspend = byt_suspend, + .resume = byt_resume, + /* DAI drivers */ .drv = byt_dai, /* all 6 SSPs may be available for cherrytrail */ From fc907cc527e6568b7486309188e545161891e1f2 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 26 May 2020 15:36:34 -0500 Subject: [PATCH 371/428] ASoC: SOF: pm: handle resume on legacy Intel platforms Add new case when set_power_state() is not supported, e.g. for Intel Baytrail/Cherrytrail legacy platforms. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Tested-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20200526203640.25980-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 5e804a7728f5..92e5f9b15f3a 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -114,8 +114,12 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } - /* Nothing further to do if resuming from a low-power D0 substate */ - if (!runtime_resume && old_state == SOF_DSP_PM_D0) + /* + * Nothing further to be done for platforms that support the low power + * D0 substate. + */ + if (!runtime_resume && sof_ops(sdev)->set_power_state && + old_state == SOF_DSP_PM_D0) return 0; sdev->fw_state = SOF_FW_BOOT_PREPARE; From 512e76724ffd07c6a5eb7d93c79d160e85465228 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 26 May 2020 15:36:35 -0500 Subject: [PATCH 372/428] ASoC: Intel: bytcr_rt5640/51: remove .ignore_suspend Low-power playback was never enabled on Baytrail devices, remove what looks like copy/paste from other machine drivers which were never submitted upstream. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200526203640.25980-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 4 ---- sound/soc/intel/boards/bytcr_rt5651.c | 3 --- 2 files changed, 7 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index fbfd53874b47..d7e42bd9b308 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -910,9 +910,6 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; - snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); - snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); - if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { /* * The firmware might enable the clock at @@ -1065,7 +1062,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .be_hw_params_fixup = byt_rt5640_codec_fixup, - .ignore_suspend = 1, .nonatomic = true, .dpcm_playback = 1, .dpcm_capture = 1, diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 214ef41e23e6..0468fc35445f 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -601,8 +601,6 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) dev_err(card->dev, "unable to add card controls\n"); return ret; } - snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); - snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) { /* @@ -775,7 +773,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .be_hw_params_fixup = byt_rt5651_codec_fixup, - .ignore_suspend = 1, .nonatomic = true, .dpcm_playback = 1, .dpcm_capture = 1, From 68224376bc2a0508f57bff67c8dcd2b5761dc939 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 26 May 2020 15:36:36 -0500 Subject: [PATCH 373/428] ASoC: Intel: byt/cht: add .pm_ops Add required .pm_ops to support suspend/resume on baytrail/cherrytrail machines. This .pm_ops is conditionally-added to avoid impacting the legacy driver where power management is handled differently. Signed-off-by: Pierre-Louis Bossart Tested-by: Enric Balletbo i Serra Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200526203640.25980-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_cx2072x.c | 3 +++ sound/soc/intel/boards/bytcht_da7213.c | 3 +++ sound/soc/intel/boards/bytcht_es8316.c | 3 +++ sound/soc/intel/boards/bytcr_rt5640.c | 3 +++ sound/soc/intel/boards/bytcr_rt5651.c | 3 +++ sound/soc/intel/boards/cht_bsw_max98090_ti.c | 3 +++ sound/soc/intel/boards/cht_bsw_nau8824.c | 3 +++ sound/soc/intel/boards/cht_bsw_rt5645.c | 3 +++ sound/soc/intel/boards/cht_bsw_rt5672.c | 3 +++ 9 files changed, 27 insertions(+) diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index c7f81a93d7c8..fad937610494 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -261,6 +261,9 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev) static struct platform_driver snd_byt_cht_cx2072x_driver = { .driver = { .name = "bytcht_cx2072x", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = snd_byt_cht_cx2072x_probe, }; diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index 5e96e7d02733..f3791ff2bad1 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -272,6 +272,9 @@ static int bytcht_da7213_probe(struct platform_device *pdev) static struct platform_driver bytcht_da7213_driver = { .driver = { .name = "bytcht_da7213", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = bytcht_da7213_probe, }; diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index ddcd070100ef..9e5fc9430628 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -605,6 +605,9 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) static struct platform_driver snd_byt_cht_es8316_mc_driver = { .driver = { .name = "bytcht_es8316", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = snd_byt_cht_es8316_mc_probe, .remove = snd_byt_cht_es8316_mc_remove, diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index d7e42bd9b308..30f70bbdf89c 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1319,6 +1319,9 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) static struct platform_driver snd_byt_rt5640_mc_driver = { .driver = { .name = "bytcr_rt5640", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = snd_byt_rt5640_mc_probe, }; diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 0468fc35445f..520e916e329c 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -1097,6 +1097,9 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) static struct platform_driver snd_byt_rt5651_mc_driver = { .driver = { .name = "bytcr_rt5651", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = snd_byt_rt5651_mc_probe, }; diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 135701738a44..767ac2ae03e2 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -616,6 +616,9 @@ static int snd_cht_mc_remove(struct platform_device *pdev) static struct platform_driver snd_cht_mc_driver = { .driver = { .name = "cht-bsw-max98090", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = snd_cht_mc_probe, .remove = snd_cht_mc_remove, diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index 67b46de2f088..2f7c94d335c1 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -282,6 +282,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev) static struct platform_driver snd_cht_mc_driver = { .driver = { .name = "cht-bsw-nau8824", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = snd_cht_mc_probe, }; diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index e64eca56e426..22de138ffa33 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -680,6 +680,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev) static struct platform_driver snd_cht_mc_driver = { .driver = { .name = "cht-bsw-rt5645", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = snd_cht_mc_probe, }; diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 097023a3ec14..7a43c70a1378 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -459,6 +459,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev) static struct platform_driver snd_cht_mc_driver = { .driver = { .name = "cht-bsw-rt5672", +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) + .pm = &snd_soc_pm_ops, +#endif }, .probe = snd_cht_mc_probe, }; From d7a1ed268993f4bc758fa509b22fc730af1623f9 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 26 May 2020 15:36:37 -0500 Subject: [PATCH 374/428] ASoC: SOF: ipc: ignore DSP replies received when they are not expected We currently ignore the reply messages from the DSP when they are not expected but call it out as an error. Change the error message to a debug message. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Tested-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20200526203640.25980-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 9 ++++----- sound/soc/sof/sof-priv.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index f7a0353596fb..36e2d4d43da4 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -335,21 +335,20 @@ int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header, EXPORT_SYMBOL(sof_ipc_tx_message_no_pm); /* handle reply message from DSP */ -int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) +void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) { struct snd_sof_ipc_msg *msg = &sdev->ipc->msg; if (msg->ipc_complete) { - dev_err(sdev->dev, "error: no reply expected, received 0x%x", + dev_dbg(sdev->dev, + "no reply expected, received 0x%x, will be ignored", msg_id); - return -EINVAL; + return; } /* wake up and return the error if we have waiters on this message ? */ msg->ipc_complete = true; wake_up(&msg->waitq); - - return 0; } EXPORT_SYMBOL(snd_sof_ipc_reply); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 3ed39b887214..64f28e082049 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -480,7 +480,7 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset); */ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev); void snd_sof_ipc_free(struct snd_sof_dev *sdev); -int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id); +void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id); void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev); int snd_sof_ipc_stream_pcm_params(struct snd_sof_dev *sdev, struct sof_ipc_pcm_params *params); From c691f0c6e267da4207392b1082d011323c3f8606 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 26 May 2020 15:36:38 -0500 Subject: [PATCH 375/428] ASoC: SOF: Intel: BYT: add .remove op Add .remove op that disables interrupts and reset the DSP for BYT and CHT platforms. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Tested-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20200526203640.25980-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 457da8fcc6a0..8784c7319098 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -456,6 +456,13 @@ static int byt_resume(struct snd_sof_dev *sdev) return 0; } +static int byt_remove(struct snd_sof_dev *sdev) +{ + byt_reset_dsp_disable_int(sdev); + + return 0; +} + /* Baytrail DAIs */ static struct snd_soc_dai_driver byt_dai[] = { { @@ -811,6 +818,7 @@ irq: const struct snd_sof_dsp_ops sof_byt_ops = { /* device init */ .probe = byt_acpi_probe, + .remove = byt_remove, /* DSP core boot / reset */ .run = byt_run, @@ -889,6 +897,7 @@ EXPORT_SYMBOL_NS(byt_chip_info, SND_SOC_SOF_BAYTRAIL); const struct snd_sof_dsp_ops sof_cht_ops = { /* device init */ .probe = byt_acpi_probe, + .remove = byt_remove, /* DSP core boot / reset */ .run = byt_run, From 3d3d1fb9ce34bc045b9d140a5f2ec531eff6a0fe Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 26 May 2020 15:36:39 -0500 Subject: [PATCH 376/428] ASoC: SOF: Intel: BYT: mask BUSY or DONE interrupts in handler The DSP may send the same interrupt multiple times before it's handled in the interrupt thread. Rather than masking it in the thread, mask it in the handler directly. This patch also removes useless checks that cannot happen, and masks that are set don't need to be re-tested. Suggested-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Tested-by: Enric Balletbo i Serra Reviewed-by: Ranjani Sridharan BugLink: https://github.com/thesofproject/linux/issues/1492 Link: https://lore.kernel.org/r/20200526203640.25980-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 46 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 8784c7319098..c6ac914ee56c 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -160,13 +160,31 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags) static irqreturn_t byt_irq_handler(int irq, void *context) { struct snd_sof_dev *sdev = context; - u64 isr; + u64 ipcx, ipcd; int ret = IRQ_NONE; - /* Interrupt arrived, check src */ - isr = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_ISRX); - if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY)) + ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX); + ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); + + if (ipcx & SHIM_BYT_IPCX_DONE) { + + /* reply message from DSP, Mask Done interrupt first */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, + SHIM_IMRX, + SHIM_IMRX_DONE, + SHIM_IMRX_DONE); ret = IRQ_WAKE_THREAD; + } + + if (ipcd & SHIM_BYT_IPCD_BUSY) { + + /* new message from DSP, Mask Busy interrupt first */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, + SHIM_IMRX, + SHIM_IMRX_BUSY, + SHIM_IMRX_BUSY); + ret = IRQ_WAKE_THREAD; + } return ret; } @@ -175,19 +193,12 @@ static irqreturn_t byt_irq_thread(int irq, void *context) { struct snd_sof_dev *sdev = context; u64 ipcx, ipcd; - u64 imrx; - imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX); ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX); + ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); /* reply message from DSP */ - if (ipcx & SHIM_BYT_IPCX_DONE && - !(imrx & SHIM_IMRX_DONE)) { - /* Mask Done interrupt before first */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_DONE, - SHIM_IMRX_DONE); + if (ipcx & SHIM_BYT_IPCX_DONE) { spin_lock_irq(&sdev->ipc_lock); @@ -207,14 +218,7 @@ static irqreturn_t byt_irq_thread(int irq, void *context) } /* new message from DSP */ - ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); - if (ipcd & SHIM_BYT_IPCD_BUSY && - !(imrx & SHIM_IMRX_BUSY)) { - /* Mask Busy interrupt before return */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_BUSY, - SHIM_IMRX_BUSY); + if (ipcd & SHIM_BYT_IPCD_BUSY) { /* Handle messages from DSP Core */ if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { From 3d2e5c480742b4a22534e72e2647b6c8c98a94a4 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Tue, 26 May 2020 15:36:40 -0500 Subject: [PATCH 377/428] ASoC: SOF: Intel: BYT: harden IPC initialization and handling On probe and reset, we should not touch the SHIM_IMRD register since it is configured by firmware. The driver only configures SHIM_IMRX with the BUSY interrupt enabled by default and DONE interrupt disabled. When sending an IPC message, the DONE interrupt is enabled until the DSP response is provided. This sequence hardens the IPC communication and avoid interrupt-related issues when adding/removing modules or during system suspend-resume transitions. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Tested-by: Enric Balletbo i Serra Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200526203640.25980-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index c6ac914ee56c..e6ba8382b1de 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -236,6 +236,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) { + /* unmask and prepare to receive Done interrupt */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_DONE, 0); + /* send the message */ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size); @@ -301,7 +305,7 @@ static void byt_host_done(struct snd_sof_dev *sdev) SHIM_BYT_IPCD_DONE, SHIM_BYT_IPCD_DONE); - /* unmask busy interrupt */ + /* unmask and prepare to receive next new message */ snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, SHIM_IMRX_BUSY, 0); } @@ -311,10 +315,6 @@ static void byt_dsp_done(struct snd_sof_dev *sdev) /* clear DONE bit - tell DSP we have completed */ snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_DONE, 0); - - /* unmask Done interrupt */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_DONE, 0); } /* @@ -453,9 +453,10 @@ static int byt_suspend(struct snd_sof_dev *sdev, u32 target_state) static int byt_resume(struct snd_sof_dev *sdev) { - /* Enable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); return 0; } @@ -606,9 +607,10 @@ irq: return ret; } - /* enable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); /* set default mailbox offset for FW ready message */ sdev->dsp_box.offset = MBOX_OFFSET; @@ -808,9 +810,10 @@ irq: return ret; } - /* enable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); /* set default mailbox offset for FW ready message */ sdev->dsp_box.offset = MBOX_OFFSET; From 9ad61b5c804090022444719d1f16e1029e002430 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Wed, 27 May 2020 16:46:08 +0800 Subject: [PATCH 378/428] ASoC: img-spdif-out: Fix runtime PM imbalance on error pm_runtime_get_sync() increments the runtime PM usage counter even the call returns an error code. Thus a pairing decrement is needed on the error handling path to keep the counter balanced. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20200527084610.4790-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- sound/soc/img/img-spdif-out.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/img/img-spdif-out.c b/sound/soc/img/img-spdif-out.c index 456c462d52fb..b1d8e4535726 100644 --- a/sound/soc/img/img-spdif-out.c +++ b/sound/soc/img/img-spdif-out.c @@ -370,8 +370,10 @@ static int img_spdif_out_probe(struct platform_device *pdev) goto err_pm_disable; } ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(&pdev->dev); goto err_suspend; + } img_spdif_out_writel(spdif, IMG_SPDIF_OUT_CTL_FS_MASK, IMG_SPDIF_OUT_CTL); From 2465d32bea35d1d56c6cfb08a96ebea3b475d8ec Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Tue, 26 May 2020 15:09:16 -0500 Subject: [PATCH 379/428] dt-bindings: sound: tlv320adcx140: Add GPI config property Add an array property that configures the General Purpose Input (GPI) register. The device has 4 GPI pins and each pin can be configured in 1 of 7 different ways. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200526200917.10385-1-dmurphy@ti.com Signed-off-by: Mark Brown --- .../bindings/sound/tlv320adcx140.yaml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml index daa6cc0e031b..e8a69b1c7ca9 100644 --- a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml +++ b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml @@ -86,6 +86,32 @@ properties: maximum: 1 default: [0, 0, 0, 0] + ti,gpi-config: + description: | + Defines the configuration for the general purpose input pins (GPI). + The array is defined as . + + 0 - (default) disabled + 1 - GPIX is configured as a general-purpose input (GPI) + 2 - GPIX is configured as a master clock input (MCLK) + 3 - GPIX is configured as an ASI input for daisy-chain (SDIN) + 4 - GPIX is configured as a PDM data input for channel 1 and channel + (PDMDIN1) + 5 - GPIX is configured as a PDM data input for channel 3 and channel + (PDMDIN2) + 6 - GPIX is configured as a PDM data input for channel 5 and channel + (PDMDIN3) + 7 - GPIX is configured as a PDM data input for channel 7 and channel + (PDMDIN4) + + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-array + - minItems: 1 + maxItems: 4 + items: + maximum: 1 + default: [0, 0, 0, 0] + required: - compatible - reg @@ -101,6 +127,7 @@ examples: reg = <0x4c>; ti,mic-bias-source = <6>; ti,pdm-edge-select = <0 1 0 1>; + ti,gpi-config = <4 5 6 7>; reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; }; }; From 3c35e79cead31c3bd79875ae90f9655dc77ad13c Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Tue, 26 May 2020 15:09:17 -0500 Subject: [PATCH 380/428] ASoC: tlv320adcx140: Add support for configuring GPI pins Add support to configure the GPI pins to the specific configuration. The pins can be disabled or be configured as data input for any of the digital mic channels. In addition the GPI can be used a a general purpose input, a Master clock input or an ASI input for daisy chaining devices. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200526200917.10385-2-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 28 ++++++++++++++++++++++++++++ sound/soc/codecs/tlv320adcx140.h | 7 +++++++ 2 files changed, 35 insertions(+) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 472d759ba8a3..dd1176574f45 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -764,6 +764,9 @@ static int adcx140_codec_probe(struct snd_soc_component *component) int pdm_count; u32 pdm_edges[ADCX140_NUM_PDM_EDGES]; u32 pdm_edge_val = 0; + int gpi_count; + u32 gpi_inputs[ADCX140_NUM_GPI_PINS]; + u32 gpi_input_val = 0; int i; int ret; @@ -809,6 +812,31 @@ static int adcx140_codec_probe(struct snd_soc_component *component) return ret; } + gpi_count = device_property_count_u32(adcx140->dev, "ti,gpi-config"); + if (gpi_count <= ADCX140_NUM_GPI_PINS && gpi_count > 0) { + ret = device_property_read_u32_array(adcx140->dev, + "ti,gpi-config", + gpi_inputs, gpi_count); + if (ret) + return ret; + + gpi_input_val = gpi_inputs[ADCX140_GPI1_INDEX] << ADCX140_GPI_SHIFT | + gpi_inputs[ADCX140_GPI2_INDEX]; + + ret = regmap_write(adcx140->regmap, ADCX140_GPI_CFG0, + gpi_input_val); + if (ret) + return ret; + + gpi_input_val = gpi_inputs[ADCX140_GPI3_INDEX] << ADCX140_GPI_SHIFT | + gpi_inputs[ADCX140_GPI4_INDEX]; + + ret = regmap_write(adcx140->regmap, ADCX140_GPI_CFG1, + gpi_input_val); + if (ret) + return ret; + } + ret = adcx140_reset(adcx140); if (ret) goto out; diff --git a/sound/soc/codecs/tlv320adcx140.h b/sound/soc/codecs/tlv320adcx140.h index 247827f315f1..39206bf1af12 100644 --- a/sound/soc/codecs/tlv320adcx140.h +++ b/sound/soc/codecs/tlv320adcx140.h @@ -132,4 +132,11 @@ #define ADCX140_NUM_PDM_EDGES 4 #define ADCX140_PDM_EDGE_SHIFT 7 +#define ADCX140_NUM_GPI_PINS 4 +#define ADCX140_GPI_SHIFT 4 +#define ADCX140_GPI1_INDEX 0 +#define ADCX140_GPI2_INDEX 1 +#define ADCX140_GPI3_INDEX 2 +#define ADCX140_GPI4_INDEX 3 + #endif /* _TLV320ADCX140_ */ From 53865b3259554389e40aeead392151c819b52a71 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Wed, 27 May 2020 16:43:24 +0800 Subject: [PATCH 381/428] ASoC: img-spdif-in: Fix runtime PM imbalance on error pm_runtime_get_sync() increments the runtime PM usage counter even the call returns an error code. Thus a pairing decrement is needed on the error handling path to keep the counter balanced. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20200527084326.4131-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- sound/soc/img/img-spdif-in.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/img/img-spdif-in.c b/sound/soc/img/img-spdif-in.c index fd639f4d082b..46ff8a3621d5 100644 --- a/sound/soc/img/img-spdif-in.c +++ b/sound/soc/img/img-spdif-in.c @@ -753,8 +753,10 @@ static int img_spdif_in_probe(struct platform_device *pdev) goto err_pm_disable; } ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(&pdev->dev); goto err_suspend; + } rst = devm_reset_control_get_exclusive(&pdev->dev, "rst"); if (IS_ERR(rst)) { From 920bef64cc5fa0e955be357bfc876179729df216 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Wed, 27 May 2020 10:46:22 +0800 Subject: [PATCH 382/428] ASoC: wm8962: Fix runtime PM imbalance on error pm_runtime_get_sync() increments the runtime PM usage counter even the call returns an error code. Thus a pairing decrement is needed on the error handling path to keep the counter balanced. Signed-off-by: Dinghao Liu Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20200527024625.9937-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 08d19df8a700..1cc23a05ffe4 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2880,6 +2880,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s ret = pm_runtime_get_sync(component->dev); if (ret < 0) { + pm_runtime_put_noidle(component->dev); dev_err(component->dev, "Failed to resume device: %d\n", ret); return ret; } @@ -3012,6 +3013,7 @@ static irqreturn_t wm8962_irq(int irq, void *data) ret = pm_runtime_get_sync(dev); if (ret < 0) { + pm_runtime_put_noidle(dev); dev_err(dev, "Failed to resume: %d\n", ret); return IRQ_NONE; } From 850ba84b5c6d4ad4d1259584ebc0338eb769f2ef Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Tue, 26 May 2020 12:52:47 -0500 Subject: [PATCH 383/428] ASoC: tlv320adcx140: Fix warnings when using W=1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the warnings when using the W=1 compiler flag. sound/soc/codecs/tlv320adcx140.c: In function ‘adcx140_reset’: sound/soc/codecs/tlv320adcx140.c:570:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] 570 | int ret = 0; | ^~~ This was set but only used in case where the reset GPIO is not defined. Have the function return the value of ret. sound/soc/codecs/tlv320adcx140.c: In function ‘adcx140_codec_probe’: sound/soc/codecs/tlv320adcx140.c:778:18: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] 778 | if (bias_source < ADCX140_MIC_BIAS_VAL_VREF || | ^ sound/soc/codecs/tlv320adcx140.c:789:18: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] 789 | if (vref_source < ADCX140_MIC_BIAS_VREF_275V || This condition will not occur since if the dt property is not set then the *_source variable is set to the default value. So there is no way that *_source can be less then 0. Which is what each #define is set to. The code just needs to make sure that the dt property is not out of the upper bounds. Reported-by: kbuild test robot Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200526175247.15309-1-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index dd1176574f45..35fe8ee5bce9 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -582,7 +582,7 @@ static int adcx140_reset(struct adcx140_priv *adcx140) /* 8.4.2: wait >= 10 ms after entering sleep mode. */ usleep_range(10000, 100000); - return 0; + return ret; } static int adcx140_hw_params(struct snd_pcm_substream *substream, @@ -775,8 +775,7 @@ static int adcx140_codec_probe(struct snd_soc_component *component) if (ret) bias_source = ADCX140_MIC_BIAS_VAL_VREF; - if (bias_source < ADCX140_MIC_BIAS_VAL_VREF || - bias_source > ADCX140_MIC_BIAS_VAL_AVDD) { + if (bias_source > ADCX140_MIC_BIAS_VAL_AVDD) { dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); return -EINVAL; } @@ -786,8 +785,7 @@ static int adcx140_codec_probe(struct snd_soc_component *component) if (ret) vref_source = ADCX140_MIC_BIAS_VREF_275V; - if (vref_source < ADCX140_MIC_BIAS_VREF_275V || - vref_source > ADCX140_MIC_BIAS_VREF_1375V) { + if (vref_source > ADCX140_MIC_BIAS_VREF_1375V) { dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); return -EINVAL; } From 185457632ba344d3100e6bdd8ba839b959521813 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 27 May 2020 03:02:10 +0000 Subject: [PATCH 384/428] ASoC: mmp-sspa: Fix return value check in asoc_mmp_sspa_probe() In case of error, the function devm_ioremap() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20200527030210.124393-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 3e37ab625f8d..4255851c71c1 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -493,13 +493,13 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) return -ENODEV; sspa->rx_base = devm_ioremap(&pdev->dev, res->start, 0x30); - if (IS_ERR(sspa->rx_base)) - return PTR_ERR(sspa->rx_base); + if (!sspa->rx_base) + return -ENOMEM; sspa->tx_base = devm_ioremap(&pdev->dev, res->start + 0x80, 0x30); - if (IS_ERR(sspa->tx_base)) - return PTR_ERR(sspa->tx_base); + if (!sspa->tx_base) + return -ENOMEM; sspa->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(sspa->clk)) From 8191743d5f9a34c0665046937eff262bffdad9a9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 27 May 2020 08:12:27 +0200 Subject: [PATCH 385/428] ALSA: usb-audio: Clean up quirk entries with macros Introduced a couple of macros to simplify some quirk entries. Just cosmetic, no functional changes. Link: https://lore.kernel.org/r/20200527061227.24915-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 93 +++++++++++++--------------------------- 1 file changed, 30 insertions(+), 63 deletions(-) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index eb89902a83be..5236f4d015c4 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -25,6 +25,21 @@ .idProduct = prod, \ .bInterfaceClass = USB_CLASS_VENDOR_SPEC +#define QUIRK_RENAME_DEVICE(_vendor, _device) \ + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ + .vendor_name = _vendor, \ + .product_name = _device, \ + .ifnum = QUIRK_NO_INTERFACE \ + } + +#define QUIRK_DEVICE_PROFILE(_vendor, _device, _profile) \ + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ + .vendor_name = _vendor, \ + .product_name = _device, \ + .profile_name = _profile, \ + .ifnum = QUIRK_NO_INTERFACE \ + } + /* FTDI devices */ { USB_DEVICE(0x0403, 0xb8d8), @@ -61,20 +76,12 @@ /* Creative/E-Mu devices */ { USB_DEVICE(0x041e, 0x3010), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Creative Labs", - .product_name = "Sound Blaster MP3+", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_RENAME_DEVICE("Creative Labs", "Sound Blaster MP3+") }, /* Creative/Toshiba Multimedia Center SB-0500 */ { USB_DEVICE(0x041e, 0x3048), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Toshiba", - .product_name = "SB-0500", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_RENAME_DEVICE("Toshiba", "SB-0500") }, { /* E-Mu 0202 USB */ @@ -207,11 +214,7 @@ .idProduct = 0x0990, .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Logitech, Inc.", - .product_name = "QuickCam Pro 9000", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_RENAME_DEVICE("Logitech, Inc.", "QuickCam Pro 9000") }, /* @@ -2596,11 +2599,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE(0x0ccd, 0x0028), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "TerraTec", - .product_name = "Aureon5.1MkII", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_RENAME_DEVICE("TerraTec", "Aureon5.1MkII") }, { USB_DEVICE(0x0ccd, 0x0035), @@ -2615,19 +2614,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */ { USB_DEVICE(0x103d, 0x0100), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Stanton", - .product_name = "ScratchAmp", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_RENAME_DEVICE("Stanton", "ScratchAmp") }, { USB_DEVICE(0x103d, 0x0101), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Stanton", - .product_name = "ScratchAmp", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_RENAME_DEVICE("Stanton", "ScratchAmp") }, /* Novation EMS devices */ @@ -2788,11 +2779,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* aka. Serato Scratch Live DJ Box */ USB_DEVICE(0x13e5, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Rane", - .product_name = "SL-1", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_RENAME_DEVICE("Rane", "SL-1") }, /* Native Instruments MK2 series */ @@ -3259,10 +3246,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), * is also used by the CM106 based cards, so make it unique. */ USB_DEVICE(0x0d8c, 0x0103), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .product_name = "Audio Advantage MicroII", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_RENAME_DEVICE(NULL, "Audio Advantage MicroII") }, /* disabled due to regression for other devices; @@ -3368,12 +3352,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), /* Dell WD15 Dock */ { USB_DEVICE(0x0bda, 0x4014), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Dell", - .product_name = "WD15 Dock", - .profile_name = "Dell-WD15-Dock", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_DEVICE_PROFILE("Dell", "WD15 Dock", "Dell-WD15-Dock") }, /* Dell WD19 Dock */ { @@ -3553,12 +3532,8 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), #define ALC1220_VB_DESKTOP(vend, prod) { \ USB_DEVICE(vend, prod), \ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ - .vendor_name = "Realtek", \ - .product_name = "ALC1220-VB-DT", \ - .profile_name = "Realtek-ALC1220-VB-Desktop", \ - .ifnum = QUIRK_NO_INTERFACE \ - } \ + QUIRK_DEVICE_PROFILE("Realtek", "ALC1220-VB-DT", \ + "Realtek-ALC1220-VB-Desktop") \ } ALC1220_VB_DESKTOP(0x0414, 0xa002), /* Gigabyte TRX40 Aorus Pro WiFi */ ALC1220_VB_DESKTOP(0x0db0, 0x0d64), /* MSI TRX40 Creator */ @@ -3574,21 +3549,13 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */ */ { USB_DEVICE(0x0414, 0xa000), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Gigabyte", - .product_name = "Aorus Master Front Headphone", - .profile_name = "Gigabyte-Aorus-Master-Front-Headphone", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_DEVICE_PROFILE("Gigabyte", "Aorus Master Front Headphone", + "Gigabyte-Aorus-Master-Front-Headphone") }, { USB_DEVICE(0x0414, 0xa001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Gigabyte", - .product_name = "Aorus Master Main Audio", - .profile_name = "Gigabyte-Aorus-Master-Main-Audio", - .ifnum = QUIRK_NO_INTERFACE - } + QUIRK_DEVICE_PROFILE("Gigabyte", "Aorus Master Main Audio", + "Gigabyte-Aorus-Master-Main-Audio") }, #undef USB_DEVICE_VENDOR_SPEC From e6825bae26812e981c4d6f93214f0259ca9a4977 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sat, 23 May 2020 14:54:55 +0200 Subject: [PATCH 386/428] ASoC: ingenic: Unconditionally depend on devicetree All boards with Ingenic SoCs probe with devicetree already, we have no use for a non-devicetree path. This solves some compilation warnings that were caused by unused variables in the case where CONFIG_OF was disabled. Reported-by: kbuild test robot Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20200523125455.12392-1-paul@crapouillou.net Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 3 +++ sound/soc/codecs/jz4725b.c | 4 +--- sound/soc/codecs/jz4740.c | 4 +--- sound/soc/codecs/jz4770.c | 2 +- sound/soc/jz4740/Kconfig | 2 +- sound/soc/jz4740/jz4740-i2s.c | 4 +--- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 683e0a94fd45..42538df2c454 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -682,6 +682,7 @@ config SND_SOC_CX2072X config SND_SOC_JZ4740_CODEC depends on MIPS || COMPILE_TEST + depends on OF select REGMAP_MMIO tristate "Ingenic JZ4740 internal CODEC" help @@ -693,6 +694,7 @@ config SND_SOC_JZ4740_CODEC config SND_SOC_JZ4725B_CODEC depends on MIPS || COMPILE_TEST + depends on OF select REGMAP tristate "Ingenic JZ4725B internal CODEC" help @@ -704,6 +706,7 @@ config SND_SOC_JZ4725B_CODEC config SND_SOC_JZ4770_CODEC depends on MIPS || COMPILE_TEST + depends on OF select REGMAP tristate "Ingenic JZ4770 internal CODEC" help diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index 2567a5d15b55..e49374c72e70 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c @@ -574,19 +574,17 @@ static int jz4725b_codec_probe(struct platform_device *pdev) return ret; } -#ifdef CONFIG_OF static const struct of_device_id jz4725b_codec_of_matches[] = { { .compatible = "ingenic,jz4725b-codec", }, { } }; MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches); -#endif static struct platform_driver jz4725b_codec_driver = { .probe = jz4725b_codec_probe, .driver = { .name = "jz4725b-codec", - .of_match_table = of_match_ptr(jz4725b_codec_of_matches), + .of_match_table = jz4725b_codec_of_matches, }, }; module_platform_driver(jz4725b_codec_driver); diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 460aa1fd1efe..c9900d1cd5c2 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -344,19 +344,17 @@ static int jz4740_codec_probe(struct platform_device *pdev) return ret; } -#ifdef CONFIG_OF static const struct of_device_id jz4740_codec_of_matches[] = { { .compatible = "ingenic,jz4740-codec", }, { } }; MODULE_DEVICE_TABLE(of, jz4740_codec_of_matches); -#endif static struct platform_driver jz4740_codec_driver = { .probe = jz4740_codec_probe, .driver = { .name = "jz4740-codec", - .of_match_table = of_match_ptr(jz4740_codec_of_matches), + .of_match_table = jz4740_codec_of_matches, }, }; diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c index e7cf2c107607..34775aa62402 100644 --- a/sound/soc/codecs/jz4770.c +++ b/sound/soc/codecs/jz4770.c @@ -937,7 +937,7 @@ static struct platform_driver jz4770_codec_driver = { .probe = jz4770_codec_probe, .driver = { .name = "jz4770-codec", - .of_match_table = of_match_ptr(jz4770_codec_of_matches), + .of_match_table = jz4770_codec_of_matches, }, }; module_platform_driver(jz4770_codec_driver); diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig index e72f826062e9..29144720cb62 100644 --- a/sound/soc/jz4740/Kconfig +++ b/sound/soc/jz4740/Kconfig @@ -2,7 +2,7 @@ config SND_JZ4740_SOC_I2S tristate "SoC Audio (I2S protocol) for Ingenic JZ4740 SoC" depends on MIPS || COMPILE_TEST - depends on HAS_IOMEM + depends on OF && HAS_IOMEM select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y if you want to use I2S protocol and I2S codec on Ingenic JZ4740 diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 403630b121f6..c7bd20104b20 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -504,7 +504,6 @@ static const struct snd_soc_component_driver jz4740_i2s_component = { .resume = jz4740_i2s_resume, }; -#ifdef CONFIG_OF static const struct of_device_id jz4740_of_matches[] = { { .compatible = "ingenic,jz4740-i2s", .data = &jz4740_i2s_soc_info }, { .compatible = "ingenic,jz4760-i2s", .data = &jz4760_i2s_soc_info }, @@ -513,7 +512,6 @@ static const struct of_device_id jz4740_of_matches[] = { { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, jz4740_of_matches); -#endif static int jz4740_i2s_dev_probe(struct platform_device *pdev) { @@ -558,7 +556,7 @@ static struct platform_driver jz4740_i2s_driver = { .probe = jz4740_i2s_dev_probe, .driver = { .name = "jz4740-i2s", - .of_match_table = of_match_ptr(jz4740_of_matches) + .of_match_table = jz4740_of_matches, }, }; From 2b1878afc8fb778a881e9a1d7d17b14e13f579dc Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Thu, 28 May 2020 15:05:10 +0800 Subject: [PATCH 387/428] ASoC: nau8810: add I2C device and compatible ID The nau8810 driver can also compatible with nau8812 and nau8814. Signed-off-by: Seven Lee Link: https://lore.kernel.org/r/20200528070510.29959-1-wtli@nuvoton.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/nau8810.txt | 5 +++-- sound/soc/codecs/nau8810.c | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/nau8810.txt b/Documentation/devicetree/bindings/sound/nau8810.txt index 05830e477acd..7deaa452b200 100644 --- a/Documentation/devicetree/bindings/sound/nau8810.txt +++ b/Documentation/devicetree/bindings/sound/nau8810.txt @@ -1,10 +1,11 @@ -NAU8810 audio CODEC +NAU8810/NAU8812/NAU8814 audio CODEC This device supports I2C only. Required properties: - - compatible : "nuvoton,nau8810" + - compatible : One of "nuvoton,nau8810" or "nuvoton,nau8812" or + "nuvoton,nau8814" - reg : the I2C address of the device. diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c index efe9fb3fb225..33ebc6398426 100644 --- a/sound/soc/codecs/nau8810.c +++ b/sound/soc/codecs/nau8810.c @@ -895,6 +895,8 @@ static int nau8810_i2c_probe(struct i2c_client *i2c, static const struct i2c_device_id nau8810_i2c_id[] = { { "nau8810", 0 }, + { "nau8812", 0 }, + { "nau8814", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, nau8810_i2c_id); @@ -902,6 +904,8 @@ MODULE_DEVICE_TABLE(i2c, nau8810_i2c_id); #ifdef CONFIG_OF static const struct of_device_id nau8810_of_match[] = { { .compatible = "nuvoton,nau8810", }, + { .compatible = "nuvoton,nau8812", }, + { .compatible = "nuvoton,nau8814", }, { } }; MODULE_DEVICE_TABLE(of, nau8810_of_match); From a50067d4f3c1d60d3fa07584aa6a0f897c1ac5b6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 May 2020 11:17:17 +0200 Subject: [PATCH 388/428] ASoC: rt5682: split i2c driver into separate module With SND_SOC_AMD_RV_RT5682_MACH using the i2c version of the driver, we can easily get a build failure when I2C is built-in but soundwire is not: WARNING: unmet direct dependencies detected for SND_SOC_RT5682 Depends on [m]: SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && (I2C [=y] || SOUNDWIRE [=m]) && (SOUNDWIRE [=m] || !SOUNDWIRE [=m]) && (I2C [=y] || !I2C [=y]) Selected by [y]: - SND_SOC_AMD_RV_RT5682_MACH [=y] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_AMD_ACP3x [=y] && I2C [=y] && CROS_EC [=y] Selected by [m]: - SND_SOC_RT5682_SDW [=m] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SOUNDWIRE [=m] && (I2C [=y] || !I2C [=y]) Rework the driver to have three separate modules, with the main driver just dealing with the common bits and the actual initialization as part of i2c and sdw specific modules. The conversion is fairly mechanical to keep it easy to review, i.e. it moves code around with the minimal required renaming and changes. Fixes: 6b8e4e7db3cd ("ASoC: amd: Add machine driver for Raven based platform") Fixes: fd443a20c2f0 ("ASoC: rt5682: fix I2C/Soundwire dependencies") Signed-off-by: Arnd Bergmann Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200528091851.2889754-1-arnd@arndb.de Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 2 +- sound/soc/codecs/Kconfig | 11 +- sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt5682-i2c.c | 306 +++++++++++++ sound/soc/codecs/rt5682-sdw.c | 459 +++++++++++++++++++- sound/soc/codecs/rt5682-sdw.h | 20 - sound/soc/codecs/rt5682.c | 773 ++------------------------------- sound/soc/codecs/rt5682.h | 32 +- sound/soc/intel/boards/Kconfig | 6 +- 9 files changed, 847 insertions(+), 764 deletions(-) create mode 100644 sound/soc/codecs/rt5682-i2c.c delete mode 100644 sound/soc/codecs/rt5682-sdw.h diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 77ffdb41bee5..e37cf72f2bab 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -29,7 +29,7 @@ config SND_SOC_AMD_ACP3x config SND_SOC_AMD_RV_RT5682_MACH tristate "AMD RV support for RT5682" - select SND_SOC_RT5682 + select SND_SOC_RT5682_I2C select SND_SOC_MAX98357A select SND_SOC_CROS_EC_CODEC select I2C_CROS_EC_TUNNEL diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 42538df2c454..986a6308818b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -168,7 +168,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT5668 imply SND_SOC_RT5670 imply SND_SOC_RT5677 - imply SND_SOC_RT5682 + imply SND_SOC_RT5682_I2C imply SND_SOC_RT5682_SDW imply SND_SOC_RT700_SDW imply SND_SOC_RT711_SDW @@ -1143,14 +1143,15 @@ config SND_SOC_RT5677_SPI config SND_SOC_RT5682 tristate - depends on I2C || SOUNDWIRE - depends on SOUNDWIRE || !SOUNDWIRE - depends on I2C || !I2C + +config SND_SOC_RT5682_I2C + tristate + depends on I2C + select SND_SOC_RT5682 config SND_SOC_RT5682_SDW tristate "Realtek RT5682 Codec - SDW" depends on SOUNDWIRE - depends on I2C || !I2C select SND_SOC_RT5682 select REGMAP_SOUNDWIRE diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 2a5a2ad14895..47ae3cebb61e 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -179,6 +179,7 @@ snd-soc-rt5677-objs := rt5677.o snd-soc-rt5677-spi-objs := rt5677-spi.o snd-soc-rt5682-objs := rt5682.o snd-soc-rt5682-sdw-objs := rt5682-sdw.o +snd-soc-rt5682-i2c-objs := rt5682-i2c.o snd-soc-rt700-objs := rt700.o rt700-sdw.o snd-soc-rt711-objs := rt711.o rt711-sdw.o snd-soc-rt715-objs := rt715.o rt715-sdw.o @@ -481,6 +482,7 @@ obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o obj-$(CONFIG_SND_SOC_RT5682) += snd-soc-rt5682.o +obj-$(CONFIG_SND_SOC_RT5682_I2C) += snd-soc-rt5682-i2c.o obj-$(CONFIG_SND_SOC_RT5682_SDW) += snd-soc-rt5682-sdw.o obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c new file mode 100644 index 000000000000..e28d08b1cd65 --- /dev/null +++ b/sound/soc/codecs/rt5682-i2c.c @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt5682.c -- RT5682 ALSA SoC audio component driver +// +// Copyright 2018 Realtek Semiconductor Corp. +// Author: Bard Liao +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rl6231.h" +#include "rt5682.h" + +static const struct rt5682_platform_data i2s_default_platform_data = { + .dmic1_data_pin = RT5682_DMIC1_DATA_GPIO2, + .dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3, + .jd_src = RT5682_JD1, + .btndet_delay = 16, + .dai_clk_names[RT5682_DAI_WCLK_IDX] = "rt5682-dai-wclk", + .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk", +}; + +static const struct regmap_config rt5682_regmap = { + .reg_bits = 16, + .val_bits = 16, + .max_register = RT5682_I2C_MODE, + .volatile_reg = rt5682_volatile_register, + .readable_reg = rt5682_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5682_reg, + .num_reg_defaults = RT5682_REG_NUM, + .use_single_read = true, + .use_single_write = true, +}; + +static void rt5682_jd_check_handler(struct work_struct *work) +{ + struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, + jd_check_work.work); + + if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL) + & RT5682_JDH_RS_MASK) { + /* jack out */ + rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); + + snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + } else { + schedule_delayed_work(&rt5682->jd_check_work, 500); + } +} + +static irqreturn_t rt5682_irq(int irq, void *data) +{ + struct rt5682_priv *rt5682 = data; + + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, msecs_to_jiffies(250)); + + return IRQ_HANDLED; +} + +static struct snd_soc_dai_driver rt5682_dai[] = { + { + .name = "rt5682-aif1", + .id = RT5682_AIF1, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .ops = &rt5682_aif1_dai_ops, + }, + { + .name = "rt5682-aif2", + .id = RT5682_AIF2, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .ops = &rt5682_aif2_dai_ops, + }, +}; + +static int rt5682_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev); + struct rt5682_priv *rt5682; + int i, ret; + unsigned int val; + + rt5682 = devm_kzalloc(&i2c->dev, sizeof(struct rt5682_priv), + GFP_KERNEL); + if (!rt5682) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt5682); + + rt5682->pdata = i2s_default_platform_data; + + if (pdata) + rt5682->pdata = *pdata; + else + rt5682_parse_dt(rt5682, &i2c->dev); + + rt5682->regmap = devm_regmap_init_i2c(i2c, &rt5682_regmap); + if (IS_ERR(rt5682->regmap)) { + ret = PTR_ERR(rt5682->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(rt5682->supplies); i++) + rt5682->supplies[i].supply = rt5682_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5682->supplies), + rt5682->supplies); + if (ret) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies), + rt5682->supplies); + if (ret) { + dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + if (gpio_is_valid(rt5682->pdata.ldo1_en)) { + if (devm_gpio_request_one(&i2c->dev, rt5682->pdata.ldo1_en, + GPIOF_OUT_INIT_HIGH, "rt5682")) + dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n"); + } + + /* Sleep for 300 ms miniumum */ + usleep_range(300000, 350000); + + regmap_write(rt5682->regmap, RT5682_I2C_MODE, 0x1); + usleep_range(10000, 15000); + + regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); + if (val != DEVICE_ID) { + dev_err(&i2c->dev, + "Device with ID register %x is not rt5682\n", val); + return -ENODEV; + } + + mutex_init(&rt5682->calibrate_mutex); + rt5682_calibrate(rt5682); + + rt5682_apply_patch_list(rt5682, &i2c->dev); + + regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); + + /* DMIC pin*/ + if (rt5682->pdata.dmic1_data_pin != RT5682_DMIC1_NULL) { + switch (rt5682->pdata.dmic1_data_pin) { + case RT5682_DMIC1_DATA_GPIO2: /* share with LRCK2 */ + regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, + RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO2); + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP2_PIN_MASK, RT5682_GP2_PIN_DMIC_SDA); + break; + + case RT5682_DMIC1_DATA_GPIO5: /* share with DACDAT1 */ + regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, + RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO5); + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP5_PIN_MASK, RT5682_GP5_PIN_DMIC_SDA); + break; + + default: + dev_warn(&i2c->dev, "invalid DMIC_DAT pin\n"); + break; + } + + switch (rt5682->pdata.dmic1_clk_pin) { + case RT5682_DMIC1_CLK_GPIO1: /* share with IRQ */ + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_DMIC_CLK); + break; + + case RT5682_DMIC1_CLK_GPIO3: /* share with BCLK2 */ + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP3_PIN_MASK, RT5682_GP3_PIN_DMIC_CLK); + break; + + default: + dev_warn(&i2c->dev, "invalid DMIC_CLK pin\n"); + break; + } + } + + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, + RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, + RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, + RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); + regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); + regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, + RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); + regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1, + RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); + regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1, + RT5682_PM_HP_MASK, RT5682_PM_HP_HV); + regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, + RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2); + + INIT_DELAYED_WORK(&rt5682->jack_detect_work, + rt5682_jack_detect_handler); + INIT_DELAYED_WORK(&rt5682->jd_check_work, + rt5682_jd_check_handler); + + if (i2c->irq) { + ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, + rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING + | IRQF_ONESHOT, "rt5682", rt5682); + if (ret) + dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); + } + + return devm_snd_soc_register_component(&i2c->dev, + &rt5682_soc_component_dev, + rt5682_dai, ARRAY_SIZE(rt5682_dai)); +} + +static void rt5682_i2c_shutdown(struct i2c_client *client) +{ + struct rt5682_priv *rt5682 = i2c_get_clientdata(client); + + rt5682_reset(rt5682); +} + +static const struct of_device_id rt5682_of_match[] = { + {.compatible = "realtek,rt5682i"}, + {}, +}; +MODULE_DEVICE_TABLE(of, rt5682_of_match); + +static const struct acpi_device_id rt5682_acpi_match[] = { + {"10EC5682", 0,}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match); + +static const struct i2c_device_id rt5682_i2c_id[] = { + {"rt5682", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id); + +static struct i2c_driver rt5682_i2c_driver = { + .driver = { + .name = "rt5682", + .of_match_table = rt5682_of_match, + .acpi_match_table = rt5682_acpi_match, + }, + .probe = rt5682_i2c_probe, + .shutdown = rt5682_i2c_shutdown, + .id_table = rt5682_i2c_id, +}; +module_i2c_driver(rt5682_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT5682 driver"); +MODULE_AUTHOR("Bard Liao "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 99dd48d2a1d6..4cecc5ce545c 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,461 @@ #include #include "rt5682.h" -#include "rt5682-sdw.h" + +#define RT5682_SDW_ADDR_L 0x3000 +#define RT5682_SDW_ADDR_H 0x3001 +#define RT5682_SDW_DATA_L 0x3004 +#define RT5682_SDW_DATA_H 0x3005 +#define RT5682_SDW_CMD 0x3008 + +static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val) +{ + struct device *dev = context; + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + unsigned int data_l, data_h; + + regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff)); + regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h); + regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l); + + *val = (data_h << 8) | data_l; + + dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val); + + return 0; +} + +static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val) +{ + struct device *dev = context; + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + + regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff)); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff)); + + dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val); + + return 0; +} + +static const struct regmap_config rt5682_sdw_indirect_regmap = { + .reg_bits = 16, + .val_bits = 16, + .max_register = RT5682_I2C_MODE, + .volatile_reg = rt5682_volatile_register, + .readable_reg = rt5682_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5682_reg, + .num_reg_defaults = RT5682_REG_NUM, + .use_single_read = true, + .use_single_write = true, + .reg_read = rt5682_sdw_read, + .reg_write = rt5682_sdw_write, +}; + +struct sdw_stream_data { + struct sdw_stream_runtime *sdw_stream; +}; + +static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + struct sdw_stream_data *stream; + + if (!sdw_stream) + return 0; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream; + + /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = stream; + else + dai->capture_dma_data = stream; + + return 0; +} + +static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_stream_data *stream; + + stream = snd_soc_dai_get_dma_data(dai, substream); + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(stream); +} + +static int rt5682_sdw_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 rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_data *stream; + int retval, port, num_channels; + unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0; + + dev_dbg(dai->dev, "%s %s", __func__, dai->name); + + stream = snd_soc_dai_get_dma_data(dai, substream); + if (!stream) + return -ENOMEM; + + if (!rt5682->slave) + return -EINVAL; + + /* SoundWire specific configuration */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = SDW_DATA_DIR_RX; + port = 1; + } else { + direction = SDW_DATA_DIR_TX; + port = 2; + } + + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = params_channels(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + num_channels = params_channels(params); + port_config.ch_mask = (1 << (num_channels)) - 1; + port_config.num = port; + + retval = sdw_stream_add_slave(rt5682->slave, &stream_config, + &port_config, 1, stream->sdw_stream); + if (retval) { + dev_err(dai->dev, "Unable to configure port\n"); + return retval; + } + + switch (params_rate(params)) { + case 48000: + val_p = RT5682_SDW_REF_1_48K; + val_c = RT5682_SDW_REF_2_48K; + break; + case 96000: + val_p = RT5682_SDW_REF_1_96K; + val_c = RT5682_SDW_REF_2_96K; + break; + case 192000: + val_p = RT5682_SDW_REF_1_192K; + val_c = RT5682_SDW_REF_2_192K; + break; + case 32000: + val_p = RT5682_SDW_REF_1_32K; + val_c = RT5682_SDW_REF_2_32K; + break; + case 24000: + val_p = RT5682_SDW_REF_1_24K; + val_c = RT5682_SDW_REF_2_24K; + break; + case 16000: + val_p = RT5682_SDW_REF_1_16K; + val_c = RT5682_SDW_REF_2_16K; + break; + case 12000: + val_p = RT5682_SDW_REF_1_12K; + val_c = RT5682_SDW_REF_2_12K; + break; + case 8000: + val_p = RT5682_SDW_REF_1_8K; + val_c = RT5682_SDW_REF_2_8K; + break; + case 44100: + val_p = RT5682_SDW_REF_1_44K; + val_c = RT5682_SDW_REF_2_44K; + break; + case 88200: + val_p = RT5682_SDW_REF_1_88K; + val_c = RT5682_SDW_REF_2_88K; + break; + case 176400: + val_p = RT5682_SDW_REF_1_176K; + val_c = RT5682_SDW_REF_2_176K; + break; + case 22050: + val_p = RT5682_SDW_REF_1_22K; + val_c = RT5682_SDW_REF_2_22K; + break; + case 11025: + val_p = RT5682_SDW_REF_1_11K; + val_c = RT5682_SDW_REF_2_11K; + break; + default: + return -EINVAL; + } + + if (params_rate(params) <= 48000) { + osr_p = RT5682_DAC_OSR_D_8; + osr_c = RT5682_ADC_OSR_D_8; + } else if (params_rate(params) <= 96000) { + osr_p = RT5682_DAC_OSR_D_4; + osr_c = RT5682_ADC_OSR_D_4; + } else { + osr_p = RT5682_DAC_OSR_D_2; + osr_c = RT5682_ADC_OSR_D_2; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK, + RT5682_SDW_REF_1_MASK, val_p); + regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1, + RT5682_DAC_OSR_MASK, osr_p); + } else { + regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK, + RT5682_SDW_REF_2_MASK, val_c); + regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1, + RT5682_ADC_OSR_MASK, osr_c); + } + + return retval; +} + +static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct sdw_stream_data *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!rt5682->slave) + return -EINVAL; + + sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream); + return 0; +} + +static struct snd_soc_dai_ops rt5682_sdw_ops = { + .hw_params = rt5682_sdw_hw_params, + .hw_free = rt5682_sdw_hw_free, + .set_sdw_stream = rt5682_set_sdw_stream, + .shutdown = rt5682_sdw_shutdown, +}; + +static struct snd_soc_dai_driver rt5682_dai[] = { + { + .name = "rt5682-aif1", + .id = RT5682_AIF1, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .ops = &rt5682_aif1_dai_ops, + }, + { + .name = "rt5682-aif2", + .id = RT5682_AIF2, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .ops = &rt5682_aif2_dai_ops, + }, + { + .name = "rt5682-sdw", + .id = RT5682_SDW, + .playback = { + .stream_name = "SDW Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .capture = { + .stream_name = "SDW Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .ops = &rt5682_sdw_ops, + }, +}; + +static int rt5682_sdw_init(struct device *dev, struct regmap *regmap, + struct sdw_slave *slave) +{ + struct rt5682_priv *rt5682; + int ret; + + rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL); + if (!rt5682) + return -ENOMEM; + + dev_set_drvdata(dev, rt5682); + rt5682->slave = slave; + rt5682->sdw_regmap = regmap; + rt5682->is_sdw = true; + + rt5682->regmap = devm_regmap_init(dev, NULL, dev, + &rt5682_sdw_indirect_regmap); + if (IS_ERR(rt5682->regmap)) { + ret = PTR_ERR(rt5682->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + /* + * Mark hw_init to false + * HW init will be performed when device reports present + */ + rt5682->hw_init = false; + rt5682->first_hw_init = false; + + mutex_init(&rt5682->calibrate_mutex); + INIT_DELAYED_WORK(&rt5682->jack_detect_work, + rt5682_jack_detect_handler); + + ret = devm_snd_soc_register_component(dev, + &rt5682_soc_component_dev, + rt5682_dai, ARRAY_SIZE(rt5682_dai)); + dev_dbg(&slave->dev, "%s\n", __func__); + + return ret; +} + +static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + int ret = 0; + unsigned int val; + + if (rt5682->hw_init) + return 0; + + regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); + if (val != DEVICE_ID) { + dev_err(dev, "Device with ID register %x is not rt5682\n", val); + return -ENODEV; + } + + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + if (!rt5682->first_hw_init) { + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(&slave->dev, 3000); + pm_runtime_use_autosuspend(&slave->dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(&slave->dev); + + pm_runtime_enable(&slave->dev); + } + + pm_runtime_get_noresume(&slave->dev); + + if (rt5682->first_hw_init) { + regcache_cache_only(rt5682->regmap, false); + regcache_cache_bypass(rt5682->regmap, true); + } + + rt5682_calibrate(rt5682); + + if (rt5682->first_hw_init) { + regcache_cache_bypass(rt5682->regmap, false); + regcache_mark_dirty(rt5682->regmap); + regcache_sync(rt5682->regmap); + + /* volatile registers */ + regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2, + RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); + + goto reinit; + } + + rt5682_apply_patch_list(rt5682, dev); + + regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); + + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, + RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, + RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); + regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, + RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); + regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1, + RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); + regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1, + RT5682_PM_HP_MASK, RT5682_PM_HP_HV); + + /* Soundwire */ + regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266); + regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700); + regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006); + regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600); + regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f); + regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000); + regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000); + regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK, + RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK, + RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW); + + regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2, + RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); + regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd042); + regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3, + RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN); + regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1, + RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + RT5682_POW_IRQ | RT5682_POW_JDH | + RT5682_POW_ANA, RT5682_POW_IRQ | + RT5682_POW_JDH | RT5682_POW_ANA); + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, + RT5682_PWR_JDH, RT5682_PWR_JDH); + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK, + RT5682_JD1_EN | RT5682_JD1_IRQ_PUL); + +reinit: + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, msecs_to_jiffies(250)); + + /* Mark Slave initialization complete */ + rt5682->hw_init = true; + rt5682->first_hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + + return ret; +} static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg) { @@ -46,7 +501,7 @@ static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg) } } -const struct regmap_config rt5682_sdw_regmap = { +static const struct regmap_config rt5682_sdw_regmap = { .name = "sdw", .reg_bits = 32, .val_bits = 8, diff --git a/sound/soc/codecs/rt5682-sdw.h b/sound/soc/codecs/rt5682-sdw.h deleted file mode 100644 index 76e6f607066e..000000000000 --- a/sound/soc/codecs/rt5682-sdw.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only - * - * rt5682-sdw.h -- RT5682 SDW ALSA SoC audio driver - * - * Copyright 2019 Realtek Semiconductor Corp. - * Author: Oder Chiou - */ - -#ifndef __RT5682_SDW_H__ -#define __RT5682_SDW_H__ - -#define RT5682_SDW_ADDR_L 0x3000 -#define RT5682_SDW_ADDR_H 0x3001 -#define RT5682_SDW_DATA_L 0x3004 -#define RT5682_SDW_DATA_H 0x3005 -#define RT5682_SDW_CMD 0x3008 - -#define RT5682_PROBE_TIMEOUT 2000 - -#endif /* __RT5682_SDW_H__ */ diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 046e6110de73..d3245123101d 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only -/* - * rt5682.c -- RT5682 ALSA SoC audio component driver - * - * Copyright 2018 Realtek Semiconductor Corp. - * Author: Bard Liao - */ +// +// rt5682.c -- RT5682 ALSA SoC audio component driver +// +// Copyright 2018 Realtek Semiconductor Corp. +// Author: Bard Liao +// #include #include @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -31,22 +30,13 @@ #include "rl6231.h" #include "rt5682.h" -#include "rt5682-sdw.h" -static const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = { +const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = { "AVDD", "MICVDD", "VBAT", }; - -static const struct rt5682_platform_data i2s_default_platform_data = { - .dmic1_data_pin = RT5682_DMIC1_DATA_GPIO2, - .dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3, - .jd_src = RT5682_JD1, - .btndet_delay = 16, - .dai_clk_names[RT5682_DAI_WCLK_IDX] = "rt5682-dai-wclk", - .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk", -}; +EXPORT_SYMBOL_GPL(rt5682_supply_names); static const struct reg_sequence patch_list[] = { {RT5682_HP_IMP_SENS_CTRL_19, 0x1000}, @@ -55,7 +45,18 @@ static const struct reg_sequence patch_list[] = { {RT5682_PLL2_INTERNAL, 0x8266}, }; -static const struct reg_default rt5682_reg[] = { +void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev) +{ + int ret; + + ret = regmap_multi_reg_write(rt5682->regmap, patch_list, + ARRAY_SIZE(patch_list)); + if (ret) + dev_warn(dev, "Failed to apply regmap patch: %d\n", ret); +} +EXPORT_SYMBOL_GPL(rt5682_apply_patch_list); + +const struct reg_default rt5682_reg[RT5682_REG_NUM] = { {0x0002, 0x8080}, {0x0003, 0x8000}, {0x0005, 0x0000}, @@ -375,8 +376,9 @@ static const struct reg_default rt5682_reg[] = { {0x03f2, 0x0800}, {0x03f3, 0x0800}, }; +EXPORT_SYMBOL_GPL(rt5682_reg); -static bool rt5682_volatile_register(struct device *dev, unsigned int reg) +bool rt5682_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case RT5682_RESET: @@ -403,8 +405,9 @@ static bool rt5682_volatile_register(struct device *dev, unsigned int reg) return false; } } +EXPORT_SYMBOL_GPL(rt5682_volatile_register); -static bool rt5682_readable_register(struct device *dev, unsigned int reg) +bool rt5682_readable_register(struct device *dev, unsigned int reg) { switch (reg) { case RT5682_RESET: @@ -733,6 +736,7 @@ static bool rt5682_readable_register(struct device *dev, unsigned int reg) return false; } } +EXPORT_SYMBOL_GPL(rt5682_readable_register); static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); @@ -800,12 +804,13 @@ static SOC_ENUM_SINGLE_DECL(rt5682_dacr_enum, static const struct snd_kcontrol_new rt5682_dac_r_mux = SOC_DAPM_ENUM("DAC R Mux", rt5682_dacr_enum); -static void rt5682_reset(struct rt5682_priv *rt5682) +void rt5682_reset(struct rt5682_priv *rt5682) { regmap_write(rt5682->regmap, RT5682_RESET, 0); if (!rt5682->is_sdw) regmap_write(rt5682->regmap, RT5682_I2C_MODE, 1); } +EXPORT_SYMBOL_GPL(rt5682_reset); /** * rt5682_sel_asrc_clk_src - select ASRC clock source for a set of filters @@ -910,8 +915,7 @@ static void rt5682_enable_push_button_irq(struct snd_soc_component *component, * * Returns detect status. */ -static int rt5682_headset_detect(struct snd_soc_component *component, - int jack_insert) +int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = &component->dapm; @@ -972,35 +976,7 @@ static int rt5682_headset_detect(struct snd_soc_component *component, dev_dbg(component->dev, "jack_type = %d\n", rt5682->jack_type); return rt5682->jack_type; } - -static irqreturn_t rt5682_irq(int irq, void *data) -{ - struct rt5682_priv *rt5682 = data; - - mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, msecs_to_jiffies(250)); - - return IRQ_HANDLED; -} - -static void rt5682_jd_check_handler(struct work_struct *work) -{ - struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, - jd_check_work.work); - - if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL) - & RT5682_JDH_RS_MASK) { - /* jack out */ - rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); - - snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, - SND_JACK_HEADSET | - SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3); - } else { - schedule_delayed_work(&rt5682->jd_check_work, 500); - } -} +EXPORT_SYMBOL_GPL(rt5682_headset_detect); static int rt5682_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) @@ -1077,7 +1053,7 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, return 0; } -static void rt5682_jack_detect_handler(struct work_struct *work) +void rt5682_jack_detect_handler(struct work_struct *work) { struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, jack_detect_work.work); @@ -1160,6 +1136,7 @@ static void rt5682_jack_detect_handler(struct work_struct *work) mutex_unlock(&rt5682->calibrate_mutex); } +EXPORT_SYMBOL_GPL(rt5682_jack_detect_handler); static const struct snd_kcontrol_new rt5682_snd_controls[] = { /* DAC Digital Volume */ @@ -2899,7 +2876,8 @@ static int rt5682_resume(struct snd_soc_component *component) regcache_cache_only(rt5682->regmap, false); regcache_sync(rt5682->regmap); - rt5682_irq(0, rt5682); + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, msecs_to_jiffies(250)); return 0; } @@ -2908,270 +2886,22 @@ static int rt5682_resume(struct snd_soc_component *component) #define rt5682_resume NULL #endif -#define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000 -#define RT5682_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) - -static const struct snd_soc_dai_ops rt5682_aif1_dai_ops = { +const struct snd_soc_dai_ops rt5682_aif1_dai_ops = { .hw_params = rt5682_hw_params, .set_fmt = rt5682_set_dai_fmt, .set_tdm_slot = rt5682_set_tdm_slot, .set_bclk_ratio = rt5682_set_bclk1_ratio, }; +EXPORT_SYMBOL_GPL(rt5682_aif1_dai_ops); -static const struct snd_soc_dai_ops rt5682_aif2_dai_ops = { +const struct snd_soc_dai_ops rt5682_aif2_dai_ops = { .hw_params = rt5682_hw_params, .set_fmt = rt5682_set_dai_fmt, .set_bclk_ratio = rt5682_set_bclk2_ratio, }; +EXPORT_SYMBOL_GPL(rt5682_aif2_dai_ops); -#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW) -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - -static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, - int direction) -{ - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - if (direction == SNDRV_PCM_STREAM_PLAYBACK) - dai->playback_dma_data = stream; - else - dai->capture_dma_data = stream; - - return 0; -} - -static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); - snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); -} - -static int rt5682_sdw_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 rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); - struct sdw_stream_config stream_config; - struct sdw_port_config port_config; - enum sdw_data_direction direction; - struct sdw_stream_data *stream; - int retval, port, num_channels; - unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0; - - dev_dbg(dai->dev, "%s %s", __func__, dai->name); - - stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) - return -ENOMEM; - - if (!rt5682->slave) - return -EINVAL; - - /* SoundWire specific configuration */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - direction = SDW_DATA_DIR_RX; - port = 1; - } else { - direction = SDW_DATA_DIR_TX; - port = 2; - } - - stream_config.frame_rate = params_rate(params); - stream_config.ch_count = params_channels(params); - stream_config.bps = snd_pcm_format_width(params_format(params)); - stream_config.direction = direction; - - num_channels = params_channels(params); - port_config.ch_mask = (1 << (num_channels)) - 1; - port_config.num = port; - - retval = sdw_stream_add_slave(rt5682->slave, &stream_config, - &port_config, 1, stream->sdw_stream); - if (retval) { - dev_err(dai->dev, "Unable to configure port\n"); - return retval; - } - - switch (params_rate(params)) { - case 48000: - val_p = RT5682_SDW_REF_1_48K; - val_c = RT5682_SDW_REF_2_48K; - break; - case 96000: - val_p = RT5682_SDW_REF_1_96K; - val_c = RT5682_SDW_REF_2_96K; - break; - case 192000: - val_p = RT5682_SDW_REF_1_192K; - val_c = RT5682_SDW_REF_2_192K; - break; - case 32000: - val_p = RT5682_SDW_REF_1_32K; - val_c = RT5682_SDW_REF_2_32K; - break; - case 24000: - val_p = RT5682_SDW_REF_1_24K; - val_c = RT5682_SDW_REF_2_24K; - break; - case 16000: - val_p = RT5682_SDW_REF_1_16K; - val_c = RT5682_SDW_REF_2_16K; - break; - case 12000: - val_p = RT5682_SDW_REF_1_12K; - val_c = RT5682_SDW_REF_2_12K; - break; - case 8000: - val_p = RT5682_SDW_REF_1_8K; - val_c = RT5682_SDW_REF_2_8K; - break; - case 44100: - val_p = RT5682_SDW_REF_1_44K; - val_c = RT5682_SDW_REF_2_44K; - break; - case 88200: - val_p = RT5682_SDW_REF_1_88K; - val_c = RT5682_SDW_REF_2_88K; - break; - case 176400: - val_p = RT5682_SDW_REF_1_176K; - val_c = RT5682_SDW_REF_2_176K; - break; - case 22050: - val_p = RT5682_SDW_REF_1_22K; - val_c = RT5682_SDW_REF_2_22K; - break; - case 11025: - val_p = RT5682_SDW_REF_1_11K; - val_c = RT5682_SDW_REF_2_11K; - break; - default: - return -EINVAL; - } - - if (params_rate(params) <= 48000) { - osr_p = RT5682_DAC_OSR_D_8; - osr_c = RT5682_ADC_OSR_D_8; - } else if (params_rate(params) <= 96000) { - osr_p = RT5682_DAC_OSR_D_4; - osr_c = RT5682_ADC_OSR_D_4; - } else { - osr_p = RT5682_DAC_OSR_D_2; - osr_c = RT5682_ADC_OSR_D_2; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK, - RT5682_SDW_REF_1_MASK, val_p); - regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1, - RT5682_DAC_OSR_MASK, osr_p); - } else { - regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK, - RT5682_SDW_REF_2_MASK, val_c); - regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1, - RT5682_ADC_OSR_MASK, osr_c); - } - - return retval; -} - -static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = - snd_soc_dai_get_dma_data(dai, substream); - - if (!rt5682->slave) - return -EINVAL; - - sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream); - return 0; -} - -static struct snd_soc_dai_ops rt5682_sdw_ops = { - .hw_params = rt5682_sdw_hw_params, - .hw_free = rt5682_sdw_hw_free, - .set_sdw_stream = rt5682_set_sdw_stream, - .shutdown = rt5682_sdw_shutdown, -}; -#endif - -static struct snd_soc_dai_driver rt5682_dai[] = { - { - .name = "rt5682-aif1", - .id = RT5682_AIF1, - .playback = { - .stream_name = "AIF1 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = RT5682_STEREO_RATES, - .formats = RT5682_FORMATS, - }, - .capture = { - .stream_name = "AIF1 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = RT5682_STEREO_RATES, - .formats = RT5682_FORMATS, - }, - .ops = &rt5682_aif1_dai_ops, - }, - { - .name = "rt5682-aif2", - .id = RT5682_AIF2, - .capture = { - .stream_name = "AIF2 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = RT5682_STEREO_RATES, - .formats = RT5682_FORMATS, - }, - .ops = &rt5682_aif2_dai_ops, - }, -#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW) - { - .name = "rt5682-sdw", - .id = RT5682_SDW, - .playback = { - .stream_name = "SDW Playback", - .channels_min = 1, - .channels_max = 2, - .rates = RT5682_STEREO_RATES, - .formats = RT5682_FORMATS, - }, - .capture = { - .stream_name = "SDW Capture", - .channels_min = 1, - .channels_max = 2, - .rates = RT5682_STEREO_RATES, - .formats = RT5682_FORMATS, - }, - .ops = &rt5682_sdw_ops, - }, -#endif -}; - -static const struct snd_soc_component_driver soc_component_dev_rt5682 = { +const struct snd_soc_component_driver rt5682_soc_component_dev = { .probe = rt5682_probe, .remove = rt5682_remove, .suspend = rt5682_suspend, @@ -3190,27 +2920,9 @@ static const struct snd_soc_component_driver soc_component_dev_rt5682 = { .endianness = 1, .non_legacy_dai_naming = 1, }; +EXPORT_SYMBOL_GPL(rt5682_soc_component_dev); -static const struct regmap_config rt5682_regmap = { - .reg_bits = 16, - .val_bits = 16, - .max_register = RT5682_I2C_MODE, - .volatile_reg = rt5682_volatile_register, - .readable_reg = rt5682_readable_register, - .cache_type = REGCACHE_RBTREE, - .reg_defaults = rt5682_reg, - .num_reg_defaults = ARRAY_SIZE(rt5682_reg), - .use_single_read = true, - .use_single_write = true, -}; - -static const struct i2c_device_id rt5682_i2c_id[] = { - {"rt5682", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id); - -static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev) +int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev) { device_property_read_u32(dev, "realtek,dmic1-data-pin", @@ -3238,8 +2950,9 @@ static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev) return 0; } +EXPORT_SYMBOL_GPL(rt5682_parse_dt); -static void rt5682_calibrate(struct rt5682_priv *rt5682) +void rt5682_calibrate(struct rt5682_priv *rt5682) { int value, count; @@ -3289,407 +3002,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) mutex_unlock(&rt5682->calibrate_mutex); } - -#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW) -static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val) -{ - struct device *dev = context; - struct rt5682_priv *rt5682 = dev_get_drvdata(dev); - unsigned int data_l, data_h; - - regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0); - regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff); - regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff)); - regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h); - regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l); - - *val = (data_h << 8) | data_l; - - dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val); - - return 0; -} - -static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val) -{ - struct device *dev = context; - struct rt5682_priv *rt5682 = dev_get_drvdata(dev); - - regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1); - regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff); - regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff)); - regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff); - regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff)); - - dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val); - - return 0; -} - -static const struct regmap_config rt5682_sdw_regmap = { - .reg_bits = 16, - .val_bits = 16, - .max_register = RT5682_I2C_MODE, - .volatile_reg = rt5682_volatile_register, - .readable_reg = rt5682_readable_register, - .cache_type = REGCACHE_RBTREE, - .reg_defaults = rt5682_reg, - .num_reg_defaults = ARRAY_SIZE(rt5682_reg), - .use_single_read = true, - .use_single_write = true, - .reg_read = rt5682_sdw_read, - .reg_write = rt5682_sdw_write, -}; - -int rt5682_sdw_init(struct device *dev, struct regmap *regmap, - struct sdw_slave *slave) -{ - struct rt5682_priv *rt5682; - int ret; - - rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL); - if (!rt5682) - return -ENOMEM; - - dev_set_drvdata(dev, rt5682); - rt5682->slave = slave; - rt5682->sdw_regmap = regmap; - rt5682->is_sdw = true; - - rt5682->regmap = devm_regmap_init(dev, NULL, dev, &rt5682_sdw_regmap); - if (IS_ERR(rt5682->regmap)) { - ret = PTR_ERR(rt5682->regmap); - dev_err(dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - - /* - * Mark hw_init to false - * HW init will be performed when device reports present - */ - rt5682->hw_init = false; - rt5682->first_hw_init = false; - - mutex_init(&rt5682->calibrate_mutex); - INIT_DELAYED_WORK(&rt5682->jack_detect_work, - rt5682_jack_detect_handler); - - ret = devm_snd_soc_register_component(dev, &soc_component_dev_rt5682, - rt5682_dai, ARRAY_SIZE(rt5682_dai)); - - dev_dbg(&slave->dev, "%s\n", __func__); - - return ret; -} -EXPORT_SYMBOL_GPL(rt5682_sdw_init); - -int rt5682_io_init(struct device *dev, struct sdw_slave *slave) -{ - struct rt5682_priv *rt5682 = dev_get_drvdata(dev); - int ret = 0; - unsigned int val; - - if (rt5682->hw_init) - return 0; - - regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); - if (val != DEVICE_ID) { - dev_err(dev, "Device with ID register %x is not rt5682\n", val); - return -ENODEV; - } - - /* - * PM runtime is only enabled when a Slave reports as Attached - */ - if (!rt5682->first_hw_init) { - /* set autosuspend parameters */ - pm_runtime_set_autosuspend_delay(&slave->dev, 3000); - pm_runtime_use_autosuspend(&slave->dev); - - /* update count of parent 'active' children */ - pm_runtime_set_active(&slave->dev); - - /* make sure the device does not suspend immediately */ - pm_runtime_mark_last_busy(&slave->dev); - - pm_runtime_enable(&slave->dev); - } - - pm_runtime_get_noresume(&slave->dev); - - if (rt5682->first_hw_init) { - regcache_cache_only(rt5682->regmap, false); - regcache_cache_bypass(rt5682->regmap, true); - } - - rt5682_calibrate(rt5682); - - if (rt5682->first_hw_init) { - regcache_cache_bypass(rt5682->regmap, false); - regcache_mark_dirty(rt5682->regmap); - regcache_sync(rt5682->regmap); - - /* volatile registers */ - regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2, - RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); - - goto reinit; - } - - ret = regmap_multi_reg_write(rt5682->regmap, patch_list, - ARRAY_SIZE(patch_list)); - if (ret) - dev_warn(dev, "Failed to apply regmap patch: %d\n", ret); - - regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); - - regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, - RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, - RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); - regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); - regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); - regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, - RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); - regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1, - RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); - regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1, - RT5682_PM_HP_MASK, RT5682_PM_HP_HV); - - /* Soundwire */ - regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266); - regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700); - regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006); - regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600); - regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f); - regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000); - regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000); - regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK, - RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK, - RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW); - - regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2, - RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); - regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd042); - regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3, - RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN); - regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1, - RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN); - regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, - RT5682_POW_IRQ | RT5682_POW_JDH | - RT5682_POW_ANA, RT5682_POW_IRQ | - RT5682_POW_JDH | RT5682_POW_ANA); - regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, - RT5682_PWR_JDH, RT5682_PWR_JDH); - regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, - RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK, - RT5682_JD1_EN | RT5682_JD1_IRQ_PUL); - -reinit: - mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, msecs_to_jiffies(250)); - - /* Mark Slave initialization complete */ - rt5682->hw_init = true; - rt5682->first_hw_init = true; - - pm_runtime_mark_last_busy(&slave->dev); - pm_runtime_put_autosuspend(&slave->dev); - - dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); - - return ret; -} -EXPORT_SYMBOL_GPL(rt5682_io_init); -#endif - -static int rt5682_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev); - struct rt5682_priv *rt5682; - int i, ret; - unsigned int val; - - rt5682 = devm_kzalloc(&i2c->dev, sizeof(struct rt5682_priv), - GFP_KERNEL); - if (!rt5682) - return -ENOMEM; - - i2c_set_clientdata(i2c, rt5682); - - rt5682->pdata = i2s_default_platform_data; - - if (pdata) - rt5682->pdata = *pdata; - else - rt5682_parse_dt(rt5682, &i2c->dev); - - rt5682->regmap = devm_regmap_init_i2c(i2c, &rt5682_regmap); - if (IS_ERR(rt5682->regmap)) { - ret = PTR_ERR(rt5682->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(rt5682->supplies); i++) - rt5682->supplies[i].supply = rt5682_supply_names[i]; - - ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5682->supplies), - rt5682->supplies); - if (ret) { - dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies), - rt5682->supplies); - if (ret) { - dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); - return ret; - } - - if (gpio_is_valid(rt5682->pdata.ldo1_en)) { - if (devm_gpio_request_one(&i2c->dev, rt5682->pdata.ldo1_en, - GPIOF_OUT_INIT_HIGH, "rt5682")) - dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n"); - } - - /* Sleep for 300 ms miniumum */ - usleep_range(300000, 350000); - - regmap_write(rt5682->regmap, RT5682_I2C_MODE, 0x1); - usleep_range(10000, 15000); - - regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); - if (val != DEVICE_ID) { - dev_err(&i2c->dev, - "Device with ID register %x is not rt5682\n", val); - return -ENODEV; - } - - mutex_init(&rt5682->calibrate_mutex); - rt5682_calibrate(rt5682); - - ret = regmap_multi_reg_write(rt5682->regmap, patch_list, - ARRAY_SIZE(patch_list)); - if (ret) - dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); - - regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); - - /* DMIC pin*/ - if (rt5682->pdata.dmic1_data_pin != RT5682_DMIC1_NULL) { - switch (rt5682->pdata.dmic1_data_pin) { - case RT5682_DMIC1_DATA_GPIO2: /* share with LRCK2 */ - regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, - RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO2); - regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, - RT5682_GP2_PIN_MASK, RT5682_GP2_PIN_DMIC_SDA); - break; - - case RT5682_DMIC1_DATA_GPIO5: /* share with DACDAT1 */ - regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, - RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO5); - regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, - RT5682_GP5_PIN_MASK, RT5682_GP5_PIN_DMIC_SDA); - break; - - default: - dev_warn(&i2c->dev, "invalid DMIC_DAT pin\n"); - break; - } - - switch (rt5682->pdata.dmic1_clk_pin) { - case RT5682_DMIC1_CLK_GPIO1: /* share with IRQ */ - regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, - RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_DMIC_CLK); - break; - - case RT5682_DMIC1_CLK_GPIO3: /* share with BCLK2 */ - regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, - RT5682_GP3_PIN_MASK, RT5682_GP3_PIN_DMIC_CLK); - break; - - default: - dev_warn(&i2c->dev, "invalid DMIC_CLK pin\n"); - break; - } - } - - regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, - RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, - RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); - regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); - regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, - RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, - RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); - regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); - regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, - RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); - regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1, - RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); - regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1, - RT5682_PM_HP_MASK, RT5682_PM_HP_HV); - regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, - RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2); - - INIT_DELAYED_WORK(&rt5682->jack_detect_work, - rt5682_jack_detect_handler); - INIT_DELAYED_WORK(&rt5682->jd_check_work, - rt5682_jd_check_handler); - - if (i2c->irq) { - ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, - rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING - | IRQF_ONESHOT, "rt5682", rt5682); - if (ret) - dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); - } - - 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) -{ - struct rt5682_priv *rt5682 = i2c_get_clientdata(client); - - rt5682_reset(rt5682); -} - -#ifdef CONFIG_OF -static const struct of_device_id rt5682_of_match[] = { - {.compatible = "realtek,rt5682i"}, - {}, -}; -MODULE_DEVICE_TABLE(of, rt5682_of_match); -#endif - -#ifdef CONFIG_ACPI -static const struct acpi_device_id rt5682_acpi_match[] = { - {"10EC5682", 0,}, - {}, -}; -MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match); -#endif - -static struct i2c_driver __maybe_unused rt5682_i2c_driver = { - .driver = { - .name = "rt5682", - .of_match_table = of_match_ptr(rt5682_of_match), - .acpi_match_table = ACPI_PTR(rt5682_acpi_match), - }, - .probe = rt5682_i2c_probe, - .shutdown = rt5682_i2c_shutdown, - .id_table = rt5682_i2c_id, -}; - -#ifdef CONFIG_I2C -module_i2c_driver(rt5682_i2c_driver); -#endif +EXPORT_SYMBOL_GPL(rt5682_calibrate); MODULE_DESCRIPTION("ASoC RT5682 driver"); MODULE_AUTHOR("Bard Liao "); diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 0baeece84ec4..f172c9ebd227 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1337,6 +1337,13 @@ #define RT5682_SAR_SOUR_BTN (0x3f) #define RT5682_SAR_SOUR_TYPE (0x0) +/* soundwire timeout */ +#define RT5682_PROBE_TIMEOUT 2000 + + +#define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT5682_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) /* System Clock Source */ enum { @@ -1418,10 +1425,29 @@ struct rt5682_priv { int jack_type; }; +extern const char *rt5682_supply_names[RT5682_NUM_SUPPLIES]; + int rt5682_sel_asrc_clk_src(struct snd_soc_component *component, unsigned int filter_mask, unsigned int clk_src); -int rt5682_sdw_init(struct device *dev, struct regmap *regmap, - struct sdw_slave *slave); -int rt5682_io_init(struct device *dev, struct sdw_slave *slave); + +void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev); + +int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert); +void rt5682_jack_detect_handler(struct work_struct *work); + +bool rt5682_volatile_register(struct device *dev, unsigned int reg); +bool rt5682_readable_register(struct device *dev, unsigned int reg); + +int rt5682_register_component(struct device *dev); +void rt5682_calibrate(struct rt5682_priv *rt5682); +void rt5682_reset(struct rt5682_priv *rt5682); +int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev); + +#define RT5682_REG_NUM 318 +extern const struct reg_default rt5682_reg[RT5682_REG_NUM]; + +extern const struct snd_soc_dai_ops rt5682_aif1_dai_ops; +extern const struct snd_soc_dai_ops rt5682_aif2_dai_ops; +extern const struct snd_soc_component_driver rt5682_soc_component_dev; #endif /* __RT5682_H__ */ diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 91ce347b3a45..46073c04364a 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -430,7 +430,7 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI - select SND_SOC_RT5682 + select SND_SOC_RT5682_I2C select SND_SOC_MAX98357A select SND_SOC_DMIC select SND_SOC_HDAC_HDMI @@ -468,7 +468,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH depends on SND_HDA_CODEC_HDMI select SND_SOC_MAX98373 select SND_SOC_RT1015 - select SND_SOC_RT5682 + select SND_SOC_RT5682_I2C select SND_SOC_DMIC select SND_SOC_HDAC_HDMI help @@ -511,7 +511,7 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_RT1011 - select SND_SOC_RT5682 + select SND_SOC_RT5682_I2C select SND_SOC_DMIC select SND_SOC_HDAC_HDMI help From 8dc1011470315501914a4527276b7b93301f3d38 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 28 May 2020 18:20:04 +0800 Subject: [PATCH 389/428] ASoC: sta32x: add missed function calls in error paths sta32x_probe() forgets to call undo functions when it fails, add the missed function calls to fix it. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20200528102004.911653-1-hslester96@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/sta32x.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index db4b3ec55311..e9ccebbc31e4 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -893,13 +893,13 @@ static int sta32x_probe(struct snd_soc_component *component) sta32x->supplies); if (ret != 0) { dev_err(component->dev, "Failed to enable supplies: %d\n", ret); - return ret; + goto err_clk_disable_unprepare; } ret = sta32x_startup_sequence(sta32x); if (ret < 0) { dev_err(component->dev, "Failed to startup device\n"); - return ret; + goto err_regulator_bulk_disable; } /* CONFA */ @@ -983,6 +983,13 @@ static int sta32x_probe(struct snd_soc_component *component) regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return 0; + +err_regulator_bulk_disable: + regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); +err_clk_disable_unprepare: + if (sta32x->xti_clk) + clk_disable_unprepare(sta32x->xti_clk); + return ret; } static void sta32x_remove(struct snd_soc_component *component) From 4a0434502191347ba8f99468f2fb2cdddc20d381 Mon Sep 17 00:00:00 2001 From: Ravulapati Vishnu vardhan rao Date: Thu, 28 May 2020 13:22:16 +0530 Subject: [PATCH 390/428] ASoC: amd: Removing unnecessary instance initialization In DMA pointer the initialzation of instance is of no use. In fact it will reinitialize the instance variable which is already opened and functional. Signed-off-by: Ravulapati Vishnu vardhan rao Link: https://lore.kernel.org/r/1590652337-21587-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-pcm-dma.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index 620b568bc414..d8f554f369a8 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -303,7 +303,6 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *prtd; struct snd_soc_card *card; - struct acp3x_platform_info *pinfo; struct i2s_stream_instance *rtd; u32 pos; u32 buffersize; @@ -312,13 +311,6 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component, prtd = substream->private_data; card = prtd->card; rtd = substream->runtime->private_data; - pinfo = snd_soc_card_get_drvdata(card); - if (pinfo) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - rtd->i2s_instance = pinfo->play_i2s_instance; - else - rtd->i2s_instance = pinfo->cap_i2s_instance; - } buffersize = frames_to_bytes(substream->runtime, substream->runtime->buffer_size); From 82ed7418736ded9c24529987d5aa9a39c185e4e9 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 27 May 2020 10:28:00 +0800 Subject: [PATCH 391/428] ASoC: topology: refine and log the header in the correct pass The check (tplg->pass == le32_to_cpu(hdr->type)) makes no sense as it is comparing two different enums, refine the element loading functions, and log the information when the header is being parsed in the corresponding parsing pass. Signed-off-by: Keyon Jie Tested-by: Vamshi Kerishna Gopal Tested-by: Cezary Rojewski Reviewed-by: Cezary Rojewski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200527022801.336264-2-yang.jie@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 50 +++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 49875978a1ce..f0a1a47d9808 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -2685,12 +2685,6 @@ static int soc_valid_header(struct soc_tplg *tplg, return -EINVAL; } - if (tplg->pass == le32_to_cpu(hdr->type)) - dev_dbg(tplg->dev, - "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n", - hdr->payload_size, hdr->type, hdr->version, - hdr->vendor_type, tplg->pass); - return 1; } @@ -2698,6 +2692,10 @@ static int soc_valid_header(struct soc_tplg *tplg, static int soc_tplg_load_header(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { + int (*elem_load)(struct soc_tplg *tplg, + struct snd_soc_tplg_hdr *hdr); + unsigned int hdr_pass; + tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr); /* check for matching ID */ @@ -2711,24 +2709,48 @@ static int soc_tplg_load_header(struct soc_tplg *tplg, case SND_SOC_TPLG_TYPE_MIXER: case SND_SOC_TPLG_TYPE_ENUM: case SND_SOC_TPLG_TYPE_BYTES: - return soc_tplg_kcontrol_elems_load(tplg, hdr); + hdr_pass = SOC_TPLG_PASS_MIXER; + elem_load = soc_tplg_kcontrol_elems_load; + break; case SND_SOC_TPLG_TYPE_DAPM_GRAPH: - return soc_tplg_dapm_graph_elems_load(tplg, hdr); + hdr_pass = SOC_TPLG_PASS_GRAPH; + elem_load = soc_tplg_dapm_graph_elems_load; + break; case SND_SOC_TPLG_TYPE_DAPM_WIDGET: - return soc_tplg_dapm_widget_elems_load(tplg, hdr); + hdr_pass = SOC_TPLG_PASS_WIDGET; + elem_load = soc_tplg_dapm_widget_elems_load; + break; case SND_SOC_TPLG_TYPE_PCM: - return soc_tplg_pcm_elems_load(tplg, hdr); + hdr_pass = SOC_TPLG_PASS_PCM_DAI; + elem_load = soc_tplg_pcm_elems_load; + break; case SND_SOC_TPLG_TYPE_DAI: - return soc_tplg_dai_elems_load(tplg, hdr); + hdr_pass = SOC_TPLG_PASS_BE_DAI; + elem_load = soc_tplg_dai_elems_load; + break; case SND_SOC_TPLG_TYPE_DAI_LINK: case SND_SOC_TPLG_TYPE_BACKEND_LINK: /* physical link configurations */ - return soc_tplg_link_elems_load(tplg, hdr); + hdr_pass = SOC_TPLG_PASS_LINK; + elem_load = soc_tplg_link_elems_load; + break; case SND_SOC_TPLG_TYPE_MANIFEST: - return soc_tplg_manifest_load(tplg, hdr); + hdr_pass = SOC_TPLG_PASS_MANIFEST; + elem_load = soc_tplg_manifest_load; + break; default: /* bespoke vendor data object */ - return soc_tplg_vendor_load(tplg, hdr); + hdr_pass = SOC_TPLG_PASS_VENDOR; + elem_load = soc_tplg_vendor_load; + break; + } + + if (tplg->pass == hdr_pass) { + dev_dbg(tplg->dev, + "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n", + hdr->payload_size, hdr->type, hdr->version, + hdr->vendor_type, tplg->pass); + return elem_load(tplg, hdr); } return 0; From c2cbd0a7194d05be501fe2cb48bcd10ff468aa87 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 27 May 2020 10:28:01 +0800 Subject: [PATCH 392/428] ASoC: topology: remove the redundant pass checks As we have check the 'pass' in the soc_elem_pass_load(), so no need to check it again in each specific elem_load function, at the same time, the tplg->pos will be reset to the next header base when the pass is mismatched, so the increasing of the tplg->pos in these cases made no sense. Here remove all of them. Signed-off-by: Keyon Jie Tested-by: Vamshi Kerishna Gopal Tested-by: Cezary Rojewski Reviewed-by: Cezary Rojewski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200527022801.336264-3-yang.jie@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 46 ++-------------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index f0a1a47d9808..9e89633676b7 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -246,8 +246,8 @@ static inline void soc_control_err(struct soc_tplg *tplg, } /* pass vendor data to component driver for processing */ -static int soc_tplg_vendor_load_(struct soc_tplg *tplg, - struct snd_soc_tplg_hdr *hdr) +static int soc_tplg_vendor_load(struct soc_tplg *tplg, + struct snd_soc_tplg_hdr *hdr) { int ret = 0; @@ -268,16 +268,6 @@ static int soc_tplg_vendor_load_(struct soc_tplg *tplg, return ret; } -/* pass vendor data to component driver for processing */ -static int soc_tplg_vendor_load(struct soc_tplg *tplg, - struct snd_soc_tplg_hdr *hdr) -{ - if (tplg->pass != SOC_TPLG_PASS_VENDOR) - return 0; - - return soc_tplg_vendor_load_(tplg, hdr); -} - /* optionally pass new dynamic widget to component driver. This is mainly for * external widgets where we can assign private data/ops */ static int soc_tplg_widget_load(struct soc_tplg *tplg, @@ -1127,12 +1117,6 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, int ret; int i; - if (tplg->pass != SOC_TPLG_PASS_MIXER) { - tplg->pos += le32_to_cpu(hdr->size) + - le32_to_cpu(hdr->payload_size); - return 0; - } - dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count, soc_tplg_get_offset(tplg)); @@ -1204,14 +1188,6 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, count = le32_to_cpu(hdr->count); - if (tplg->pass != SOC_TPLG_PASS_GRAPH) { - tplg->pos += - le32_to_cpu(hdr->size) + - le32_to_cpu(hdr->payload_size); - - return 0; - } - if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_dapm_graph_elem), count, le32_to_cpu(hdr->payload_size), "graph")) { @@ -1741,9 +1717,6 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, count = le32_to_cpu(hdr->count); - if (tplg->pass != SOC_TPLG_PASS_WIDGET) - return 0; - dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count); for (i = 0; i < count; i++) { @@ -2101,9 +2074,6 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, count = le32_to_cpu(hdr->count); - if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) - return 0; - /* check the element size and count */ pcm = (struct snd_soc_tplg_pcm *)tplg->pos; size = le32_to_cpu(pcm->size); @@ -2386,12 +2356,6 @@ static int soc_tplg_link_elems_load(struct soc_tplg *tplg, count = le32_to_cpu(hdr->count); - if (tplg->pass != SOC_TPLG_PASS_LINK) { - tplg->pos += le32_to_cpu(hdr->size) + - le32_to_cpu(hdr->payload_size); - return 0; - } - /* check the element size and count */ link = (struct snd_soc_tplg_link_config *)tplg->pos; size = le32_to_cpu(link->size); @@ -2528,9 +2492,6 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg, count = le32_to_cpu(hdr->count); - if (tplg->pass != SOC_TPLG_PASS_BE_DAI) - return 0; - /* config the existing BE DAIs */ for (i = 0; i < count; i++) { dai = (struct snd_soc_tplg_dai *)tplg->pos; @@ -2610,9 +2571,6 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, bool abi_match; int ret = 0; - if (tplg->pass != SOC_TPLG_PASS_MANIFEST) - return 0; - manifest = (struct snd_soc_tplg_manifest *)tplg->pos; /* check ABI version by size, create a new manifest if abi not match */ From 65bd91dd6957390c42a0491b9622cf31a2cdb140 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Fri, 29 May 2020 09:22:28 +0800 Subject: [PATCH 393/428] ASoC: img-i2s-out: Fix runtime PM imbalance on error pm_runtime_get_sync() increments the runtime PM usage counter even the call returns an error code. Thus a pairing decrement is needed on the error handling path to keep the counter balanced. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20200529012230.5863-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-out.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c index db052ec17d5d..b56a18e7f3ac 100644 --- a/sound/soc/img/img-i2s-out.c +++ b/sound/soc/img/img-i2s-out.c @@ -347,8 +347,10 @@ static int img_i2s_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) chan_control_mask = IMG_I2S_OUT_CHAN_CTL_CLKT_MASK; ret = pm_runtime_get_sync(i2s->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(i2s->dev); return ret; + } img_i2s_out_disable(i2s); @@ -488,8 +490,10 @@ static int img_i2s_out_probe(struct platform_device *pdev) goto err_pm_disable; } ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(&pdev->dev); goto err_suspend; + } reg = IMG_I2S_OUT_CTL_FRM_SIZE_MASK; img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL); From c8b47d63ad8755780b6b70dbe57ab8333bcc4a0f Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 28 May 2020 09:47:11 -0500 Subject: [PATCH 394/428] ASoC: tlv320adcx140: Fix dt-binding-check issue Fix dt-binding-check issue ti,gpi-config:0:0: 4 is greater than the maximum of 1 ti,gpi-config:0:1: 5 is greater than the maximum of 1 ti,gpi-config:0:2: 6 is greater than the maximum of 1 ti,gpi-config:0:3: 7 is greater than the maximum of 1 Reported-by: Rob Herring Signed-off-by: Dan Murphy Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200528144711.18065-1-dmurphy@ti.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/tlv320adcx140.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml index e8a69b1c7ca9..306ac3d006dc 100644 --- a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml +++ b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml @@ -109,7 +109,7 @@ properties: - minItems: 1 maxItems: 4 items: - maximum: 1 + maximum: 7 default: [0, 0, 0, 0] required: From 2aec8ccc1a814ca41b70710e1960afd034d1e3ab Mon Sep 17 00:00:00 2001 From: "derek.fang" Date: Fri, 29 May 2020 19:05:10 +0800 Subject: [PATCH 395/428] ASoC: rt1015: Enable class-D silence and clock detections Avoid noise under bypass boost mode. Signed-off-by: derek.fang Link: https://lore.kernel.org/r/1590750310-30085-1-git-send-email-derek.fang@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 5eb07a430ae3..67e2e944d21b 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -475,7 +475,7 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, snd_soc_component_write(component, RT1015_CLSD_INTERNAL9, 0x0140); snd_soc_component_write(component, - RT1015_GAT_BOOST, 0x00fe); + RT1015_GAT_BOOST, 0x0efe); snd_soc_component_write(component, RT1015_PWR_STATE_CTRL, 0x000d); msleep(500); From 36124fb19f1ae68a500cd76a76d40c6e81bee346 Mon Sep 17 00:00:00 2001 From: Xiyu Yang Date: Mon, 25 May 2020 22:12:46 +0800 Subject: [PATCH 396/428] ASoC: fsl_asrc_dma: Fix dma_chan leak when config DMA channel failed fsl_asrc_dma_hw_params() invokes dma_request_channel() or fsl_asrc_get_dma_channel(), which returns a reference of the specified dma_chan object to "pair->dma_chan[dir]" with increased refcnt. The reference counting issue happens in one exception handling path of fsl_asrc_dma_hw_params(). When config DMA channel failed for Back-End, the function forgets to decrease the refcnt increased by dma_request_channel() or fsl_asrc_get_dma_channel(), causing a refcnt leak. Fix this issue by calling dma_release_channel() when config DMA channel failed. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan Link: https://lore.kernel.org/r/1590415966-52416-1-git-send-email-xiyuyang19@fudan.edu.cn Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc_dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index e5d1b218acf8..d6a3fc5f87e5 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -261,6 +261,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be); if (ret) { dev_err(dev, "failed to config DMA channel for Back-End\n"); + dma_release_channel(pair->dma_chan[dir]); return ret; } From 28ff437a44fa618a14bc7402c7472b278af4c9eb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 29 May 2020 07:36:13 -0500 Subject: [PATCH 397/428] ASoC: reduce verbosity of error messages for sof-dai and sof-link Recent changes result in multiple dmesg traces such as: [ 14.410435] Audio Port: ASoC: error at snd_soc_link_startup on Audio Port: 1 [ 14.410446] sst-mfld-platform sst-mfld-platform: ASoC: error at snd_soc_dai_startup on media-cpu-dai: 1 These messages are not really errors, when dai and dai-link callbacks return the value of e.g. snd_pcm_hw_constraint_single() the result is "Positive if the value is changed, zero if it's not changed, or a negative error code" Add a simple test to skip the checks for positive returned values Suggested-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200529123613.13447-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-dai.c | 6 +++++- sound/soc/soc-link.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 2c6ac3b0afa5..b05e18b63a1c 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -14,10 +14,14 @@ static inline int _soc_dai_ret(struct snd_soc_dai *dai, const char *func, int ret) { + /* Positive, Zero values are not errors */ + if (ret >= 0) + return ret; + + /* Negative values might be errors */ switch (ret) { case -EPROBE_DEFER: case -ENOTSUPP: - case 0: break; default: dev_err(dai->dev, diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 248e1be4e1eb..f849278beba0 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -12,10 +12,14 @@ static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd, const char *func, int ret) { + /* Positive, Zero values are not errors */ + if (ret >= 0) + return ret; + + /* Negative values might be errors */ switch (ret) { case -EPROBE_DEFER: case -ENOTSUPP: - case 0: break; default: dev_err(rtd->dev, From 68f8043ed13e636c6f04ac1c0831e17681d392ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E7=81=BF=E7=81=BF?= Date: Fri, 29 May 2020 18:12:44 +0800 Subject: [PATCH 398/428] Subject: [PATCH v2] ASoC: soc-pcm: fix BE dai not hw_free and shutdown during mixer update FE state is SND_SOC_DPCM_STATE_PREPARE now, BE1 is used by FE. Later when new BE2 is added to FE by mixer update, it will call dpcm_run_update_startup() to update BE2's state, but unfortunately BE2 .prepare() meets error, it will disconnect all non started BE. This make BE1 dai skip .hw_free() and .shutdown(), and the BE1 users will never decrease to zero. Signed-off-by: zhucancan Link: https://lore.kernel.org/r/ALMAWwB5CP9aAcKXCU5FzqqF.1.1590747164172.Hmail.zhucancan@vivo.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 80dd3cf6200c..276505fb9d50 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2611,12 +2611,12 @@ hw_free: close: dpcm_be_dai_shutdown(fe, stream); disconnect: - /* disconnect any non started BEs */ + /* disconnect any closed BEs */ spin_lock_irqsave(&fe->card->dpcm_lock, flags); for_each_dpcm_be(fe, stream, dpcm) { struct snd_soc_pcm_runtime *be = dpcm->be; - if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) - dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; + if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) + dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; } spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); From af89e7dac521f5e087b6b2706bb0623107f74c83 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 29 May 2020 10:04:08 -0500 Subject: [PATCH 399/428] ASoC: SOF: Intel: Baytrail: fix 'defined but not used' warnings With the allmodconfig option, CONFIG_SND_SOC_SOF_BAYTRAIL is disabled due to mutual exclusion with the legacy driver. This generates 'defined by not used' warnings. suspend/resume/remove are only supported for Baytrail for now, so move the code under the CONFIG_SND_SOC_SOF_BAYTRAIL checks. Fixes: ddcccd543f5d ("ASoC: SOF: Intel: byt: Add PM callbacks") Reported-by: Stephen Rothwell Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200529150408.17236-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index e6ba8382b1de..49f67f1b94e0 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -432,42 +432,6 @@ static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach, mach_params->platform = dev_name(dev); } -static void byt_reset_dsp_disable_int(struct snd_sof_dev *sdev) -{ - /* Disable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x3); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x3); - - /* Put DSP into reset, set reset vector */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR, - SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL, - SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL); -} - -static int byt_suspend(struct snd_sof_dev *sdev, u32 target_state) -{ - byt_reset_dsp_disable_int(sdev); - - return 0; -} - -static int byt_resume(struct snd_sof_dev *sdev) -{ - /* enable BUSY and disable DONE Interrupt by default */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_BUSY | SHIM_IMRX_DONE, - SHIM_IMRX_DONE); - - return 0; -} - -static int byt_remove(struct snd_sof_dev *sdev) -{ - byt_reset_dsp_disable_int(sdev); - - return 0; -} - /* Baytrail DAIs */ static struct snd_soc_dai_driver byt_dai[] = { { @@ -695,6 +659,42 @@ EXPORT_SYMBOL_NS(tng_chip_info, SND_SOC_SOF_MERRIFIELD); #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +static void byt_reset_dsp_disable_int(struct snd_sof_dev *sdev) +{ + /* Disable Interrupt from both sides */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x3); + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x3); + + /* Put DSP into reset, set reset vector */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR, + SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL, + SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL); +} + +static int byt_suspend(struct snd_sof_dev *sdev, u32 target_state) +{ + byt_reset_dsp_disable_int(sdev); + + return 0; +} + +static int byt_resume(struct snd_sof_dev *sdev) +{ + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); + + return 0; +} + +static int byt_remove(struct snd_sof_dev *sdev) +{ + byt_reset_dsp_disable_int(sdev); + + return 0; +} + static const struct snd_sof_debugfs_map cht_debugfs[] = { {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE, SOF_DEBUGFS_ACCESS_ALWAYS}, From 89d73ccab20a684d8446cea4d8ac6a2608c8d390 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 29 May 2020 19:03:58 +0300 Subject: [PATCH 400/428] ASoC: SOF: Intel: hda: fix generic hda codec support Add support for using generic codec driver with SOF. Generic driver is used if: - snd_sof_intel_hda_common.hda_model="generic" is set, or - fallback if no other codec driver is found The implementation is aligned with snd-hda-intel driver, and fixes audio support for systems like Acer Swift 3 SF314-57G, on which this issue was originally reported. Signed-off-by: Kai Vehmanen Reviewed-by: Hui Wang Reviewed-by: Guennadi Liakhovetski Reviewed-by: Pierre-Louis Bossart BugLink: https://github.com/thesofproject/linux/issues/1807 BugLink: https://bugs.launchpad.net/bugs/1877757 Link: https://lore.kernel.org/r/20200529160358.12134-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 51 +++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index c3299be119a1..2c5c451fa19d 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -24,19 +24,44 @@ #define IDISP_VID_INTEL 0x80860000 /* load the legacy HDA codec driver */ -static int hda_codec_load_module(struct hda_codec *codec) +static int request_codec_module(struct hda_codec *codec) { #ifdef MODULE char alias[MODULE_NAME_LEN]; - const char *module = alias; + const char *mod = NULL; - snd_hdac_codec_modalias(&codec->core, alias, sizeof(alias)); - dev_dbg(&codec->core.dev, "loading codec module: %s\n", module); - request_module(module); + switch (codec->probe_id) { + case HDA_CODEC_ID_GENERIC: +#if IS_MODULE(CONFIG_SND_HDA_GENERIC) + mod = "snd-hda-codec-generic"; #endif + break; + default: + snd_hdac_codec_modalias(&codec->core, alias, sizeof(alias)); + mod = alias; + break; + } + + if (mod) { + dev_dbg(&codec->core.dev, "loading codec module: %s\n", mod); + request_module(mod); + } +#endif /* MODULE */ return device_attach(hda_codec_dev(codec)); } +static int hda_codec_load_module(struct hda_codec *codec) +{ + int ret = request_codec_module(codec); + + if (ret <= 0) { + codec->probe_id = HDA_CODEC_ID_GENERIC; + ret = request_codec_module(codec); + } + + return ret; +} + /* enable controller wake up event for all codecs with jack connectors */ void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) { @@ -78,6 +103,13 @@ void hda_codec_jack_check(struct snd_sof_dev *sdev) {} EXPORT_SYMBOL_NS(hda_codec_jack_wake_enable, SND_SOC_SOF_HDA_AUDIO_CODEC); EXPORT_SYMBOL_NS(hda_codec_jack_check, SND_SOC_SOF_HDA_AUDIO_CODEC); +#if IS_ENABLED(CONFIG_SND_HDA_GENERIC) +#define is_generic_config(bus) \ + ((bus)->modelname && !strcmp((bus)->modelname, "generic")) +#else +#define is_generic_config(x) 0 +#endif + /* probe individual codec */ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, bool hda_codec_use_common_hdmi) @@ -87,6 +119,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, #endif struct hda_bus *hbus = sof_to_hbus(sdev); struct hdac_device *hdev; + struct hda_codec *codec; u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; u32 resp = -1; @@ -108,6 +141,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, hda_priv->codec.bus = hbus; hdev = &hda_priv->codec.core; + codec = &hda_priv->codec; ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev); if (ret < 0) @@ -122,6 +156,11 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, hda_priv->need_display_power = true; } + if (is_generic_config(hbus)) + codec->probe_id = HDA_CODEC_ID_GENERIC; + else + codec->probe_id = 0; + /* * if common HDMI codec driver is not used, codec load * is skipped here and hdac_hdmi is used instead @@ -129,7 +168,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, if (hda_codec_use_common_hdmi || (resp & 0xFFFF0000) != IDISP_VID_INTEL) { hdev->type = HDA_DEV_LEGACY; - ret = hda_codec_load_module(&hda_priv->codec); + ret = hda_codec_load_module(codec); /* * handle ret==0 (no driver bound) as an error, but pass * other return codes without modification From f99e24a6778a065dad732b916b2648352609c79a Mon Sep 17 00:00:00 2001 From: Thomas Ebeling Date: Fri, 29 May 2020 19:32:56 +0200 Subject: [PATCH 401/428] ALSA: usb-audio: Fixing usage of plain int instead of NULL As reported by kbuild test robot, mixer quirks for RME Babyface Pro used plain integer instead of NULL. Fixes: 3e8f3bd04716 ("ALSA: usb-audio: RME Babyface Pro mixer patch") Signed-off-by: Thomas Ebeling Reported-by: kbuild test robot Link: https://lore.kernel.org/r/20200529173248.zzawijfvw73kzjxt@bollie.ca9.eu Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index aad2683ff793..b6bcf2f92383 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2255,7 +2255,7 @@ static int snd_bbfpro_ctl_update(struct usb_mixer_interface *mixer, u8 reg, err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), usb_req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - usb_val, usb_idx, 0, 0); + usb_val, usb_idx, NULL, 0); snd_usb_unlock_shutdown(chip); return err; @@ -2394,7 +2394,7 @@ static int snd_bbfpro_vol_update(struct usb_mixer_interface *mixer, u16 index, SND_BBFPRO_USBREQ_MIXER, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - usb_val, usb_idx, 0, 0); + usb_val, usb_idx, NULL, 0); snd_usb_unlock_shutdown(chip); return err; From 8f529f0175aa02266542714a569b885dd145b61c Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Fri, 29 May 2020 14:35:45 -0500 Subject: [PATCH 402/428] ASoC: intel: add depends on SND_SOC_SOF_HDA_AUDIO_CODEC for common hdmi If the driver uses common hdmi, SND_SOC_SOF_HDA_AUDIO_CODEC is required to be enabled. Otherwise, the legacy hda codec driver will not be used. Signed-off-by: Libin Yang Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200529193547.6077-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 46073c04364a..a2a5798c9139 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -411,13 +411,13 @@ config SND_SOC_INTEL_KBL_RT5660_MACH endif ## SND_SOC_INTEL_KBL -if SND_SOC_SOF_GEMINILAKE && SND_SOC_SOF_HDA_LINK +if SND_SOC_SOF_GEMINILAKE config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH tristate "GLK with DA7219 and MAX98357A in I2S Mode" depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI + depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON help This adds support for ASoC machine driver for Geminilake platforms @@ -429,7 +429,7 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH tristate "GLK with RT5682 and MAX98357A in I2S Mode" depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI + depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_RT5682_I2C select SND_SOC_MAX98357A select SND_SOC_DMIC @@ -440,7 +440,7 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH Say Y if you have such a device. If unsure select "N". -endif ## SND_SOC_SOF_GEMINILAKE && SND_SOC_SOF_HDA_LINK +endif ## SND_SOC_SOF_GEMINILAKE if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC @@ -463,9 +463,9 @@ if SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL config SND_SOC_INTEL_SOF_RT5682_MACH tristate "SOF with rt5682 codec in I2S Mode" depends on I2C && ACPI && GPIOLIB - depends on (SND_SOC_SOF_HDA_LINK && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ + depends on ((SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC) &&\ + (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) - depends on SND_HDA_CODEC_HDMI select SND_SOC_MAX98373 select SND_SOC_RT1015 select SND_SOC_RT5682_I2C @@ -509,7 +509,7 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH tristate "CML with RT1011 and RT5682 in I2S Mode" depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI + depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_RT1011 select SND_SOC_RT5682_I2C select SND_SOC_DMIC @@ -528,7 +528,7 @@ config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH tristate "SOF with DA7219 and MAX98373/MAX98360A in I2S Mode" depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI + depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_DA7219 select SND_SOC_MAX98373 select SND_SOC_DMIC @@ -546,7 +546,7 @@ config SND_SOC_INTEL_EHL_RT5660_MACH tristate "EHL with RT5660 in I2S mode" depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI + depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_RT5660 select SND_SOC_DMIC help @@ -563,7 +563,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE - depends on SND_HDA_CODEC_HDMI + depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_RT700_SDW select SND_SOC_RT711_SDW select SND_SOC_RT1308_SDW From 38acab2d61073ed4a684533d46505feba3eecf67 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Fri, 29 May 2020 14:35:46 -0500 Subject: [PATCH 403/428] ASoC: sof-sdw: remove CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC condition As CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC is always enabled in sof-soundwire driver, let's remove the test of CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC in the code. Signed-off-by: Libin Yang Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200529193547.6077-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 8 -------- sound/soc/intel/boards/sof_sdw_hdmi.c | 7 ------- 2 files changed, 15 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 47820316df57..e1c1a8ba78e6 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -663,9 +663,7 @@ static int sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card) { int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) struct snd_soc_dai_link_component *idisp_components; -#endif struct snd_soc_dai_link_component *ssp_components; struct snd_soc_acpi_mach_params *mach_params; const struct snd_soc_acpi_link_adr *adr_link; @@ -686,10 +684,8 @@ static int sof_card_dai_links_create(struct device *dev, for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) codec_info_list[i].amp_num = 0; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) hdmi_num = sof_sdw_quirk & SOF_SDW_TGL_HDMI ? SOF_TGL_HDMI_COUNT : SOF_PRE_TGL_HDMI_COUNT; -#endif ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); /* @@ -849,7 +845,6 @@ DMIC: INC_ID(be_id, cpu_id, link_id); } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) /* HDMI */ if (hdmi_num > 0) { idisp_components = devm_kcalloc(dev, hdmi_num, @@ -886,7 +881,6 @@ DMIC: sof_sdw_hdmi_init, NULL); INC_ID(be_id, cpu_id, link_id); } -#endif card->dai_link = links; card->num_links = num_links; @@ -920,9 +914,7 @@ static int mc_probe(struct platform_device *pdev) dmi_check_system(sof_sdw_quirk_table); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) INIT_LIST_HEAD(&ctx->hdmi_pcm_list); -#endif card->dev = &pdev->dev; diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c index b60852339330..0654b38a7e0d 100644 --- a/sound/soc/intel/boards/sof_sdw_hdmi.c +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -16,7 +16,6 @@ #include "../../codecs/hdac_hdmi.h" #include "hda_dsp_common.h" -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) static struct snd_soc_jack hdmi[MAX_HDMI_NUM]; struct hdmi_pcm { @@ -89,9 +88,3 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card) return hdac_hdmi_jack_port_init(component, &card->dapm); } -#else -int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card) -{ - return 0; -} -#endif From 1e7cb64b0ab5a810b05ed49dd263605add41ac5d Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Fri, 29 May 2020 14:35:47 -0500 Subject: [PATCH 404/428] ASoC: sof_pcm512x: remove CONFIG_SND_HDA_CODEC_HDMI condition As CONFIG_SND_HDA_CODEC_HDMI is always enabled in sof_pcm512x, let's remove the test of CONFIG_SND_HDA_CODEC_HDMI in the sof_pcm512x driver. Signed-off-by: Libin Yang Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200529193547.6077-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_pcm512x.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index f983c7fbb1d1..9fa8a4911276 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -126,7 +126,6 @@ static struct snd_soc_dai_link_component platform_component[] = { } }; -#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) static int sof_card_late_probe(struct snd_soc_card *card) { struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); @@ -146,12 +145,6 @@ static int sof_card_late_probe(struct snd_soc_card *card) return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component); } -#else -static int sof_card_late_probe(struct snd_soc_card *card) -{ - return 0; -} -#endif static const struct snd_kcontrol_new sof_controls[] = { SOC_DAPM_PIN_SWITCH("Ext Spk"), @@ -374,14 +367,12 @@ static int sof_audio_probe(struct platform_device *pdev) sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(2); } else { dmic_be_num = 2; -#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) if (mach->mach_params.common_hdmi_codec_drv && (mach->mach_params.codec_mask & IDISP_CODEC_MASK)) ctx->idisp_codec = true; /* links are always present in topology */ hdmi_num = 3; -#endif } dmi_check_system(sof_pcm512x_quirk_table); From b6f10d3f2e6dfccf58c54e81c8af586b66a80ce4 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Tue, 26 May 2020 22:01:43 +0100 Subject: [PATCH 405/428] dt-bindings: ASoC: renesas,rsnd: Add r8a7742 support Document RZ/G1H (R8A7742) SoC bindings. Signed-off-by: Lad Prabhakar Reviewed-by: Marian-Cristian Rotariu Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Link: https://lore.kernel.org/r/1590526904-13855-2-git-send-email-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/renesas,rsnd.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 797fd035434c..1596f0d1e2fe 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -263,6 +263,7 @@ Required properties: "renesas,rcar_sound-gen2" if generation2 (or RZ/G1) "renesas,rcar_sound-gen3" if generation3 (or RZ/G2) Examples with soctypes are: + - "renesas,rcar_sound-r8a7742" (RZ/G1H) - "renesas,rcar_sound-r8a7743" (RZ/G1M) - "renesas,rcar_sound-r8a7744" (RZ/G1N) - "renesas,rcar_sound-r8a7745" (RZ/G1E) From 317ec67593100f0ef0d017bcd73d42704d73fdb6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:47:37 +0900 Subject: [PATCH 406/428] ASoC: soc.h: convert bool to bit field for snd_soc_card snd_soc_card has many bool, but it can be bit field. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87d06o25l2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index a7fa64260108..11ee3ed87aa1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -820,7 +820,7 @@ struct snd_soc_dai_link { const struct snd_soc_compr_ops *compr_ops; /* Mark this pcm with non atomic ops */ - bool nonatomic; + unsigned int nonatomic:1; /* For unidirectional dai links */ unsigned int playback_only:1; @@ -1016,9 +1016,6 @@ struct snd_soc_card { spinlock_t dpcm_lock; - bool instantiated; - bool topology_shortname_created; - int (*probe)(struct snd_soc_card *card); int (*late_probe)(struct snd_soc_card *card); int (*remove)(struct snd_soc_card *card); @@ -1079,8 +1076,6 @@ struct snd_soc_card { int num_of_dapm_widgets; const struct snd_soc_dapm_route *of_dapm_routes; int num_of_dapm_routes; - bool fully_routed; - bool disable_route_checks; /* lists of probed devices belonging to this card */ struct list_head component_dev_list; @@ -1107,6 +1102,12 @@ struct snd_soc_card { #endif u32 pop_time; + /* bit field */ + unsigned int instantiated:1; + unsigned int topology_shortname_created:1; + unsigned int fully_routed:1; + unsigned int disable_route_checks:1; + void *drvdata; }; #define for_each_card_prelinks(card, i, link) \ From 1793936bc9081d541da2ecd2af83eded7e6212a7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:47:46 +0900 Subject: [PATCH 407/428] ASoC: add soc-card.c Current ALSA SoC has some snd_soc_card_xxx() functions, and card->xxx() callbacks. But, it is implemented randomly at random place. To collect all card related functions into one place, this patch creats new soc-card.c. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87blm825kt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 11 +++++++++++ include/sound/soc.h | 1 + sound/soc/Makefile | 2 +- sound/soc/soc-card.c | 26 ++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 include/sound/soc-card.h create mode 100644 sound/soc/soc-card.c diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h new file mode 100644 index 000000000000..997809bb3afb --- /dev/null +++ b/include/sound/soc-card.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * soc-card.h + * + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto + */ +#ifndef __SOC_CARD_H +#define __SOC_CARD_H + +#endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 11ee3ed87aa1..5b880e29d106 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1450,5 +1450,6 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) } #include +#include #endif diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 70a5f19ea3a1..7f1747518e79 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o -snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o +snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o soc-card.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c new file mode 100644 index 000000000000..4bc6f26ea8cb --- /dev/null +++ b/sound/soc/soc-card.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// soc-card.c +// +// Copyright (C) 2019 Renesas Electronics Corp. +// Kuninori Morimoto +// +#include + +#define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret) +static inline int _soc_card_ret(struct snd_soc_card *card, + const char *func, int ret) +{ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + case 0: + break; + default: + dev_err(card->dev, + "ASoC: error at %s on %s: %d\n", + func, card->name, ret); + } + + return ret; +} From 209c6cdfd28360f030f88ae9adb69f633e6bcd2d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:47:56 +0900 Subject: [PATCH 408/428] ASoC: soc-card: move snd_soc_card_get_kcontrol() to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87a71s25kj.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 3 +++ include/sound/soc.h | 2 -- sound/soc/soc-card.c | 16 ++++++++++++++++ sound/soc/soc-core.c | 16 ---------------- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 997809bb3afb..c601eddf0975 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -8,4 +8,7 @@ #ifndef __SOC_CARD_H #define __SOC_CARD_H +struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, + const char *name); + #endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 5b880e29d106..f93827c6be51 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -582,8 +582,6 @@ static inline int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, void *data, const char *long_name, const char *prefix); -struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, - const char *name); int snd_soc_add_component_controls(struct snd_soc_component *component, const struct snd_kcontrol_new *controls, unsigned int num_controls); int snd_soc_add_card_controls(struct snd_soc_card *soc_card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 4bc6f26ea8cb..340ab682cc76 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -24,3 +24,19 @@ static inline int _soc_card_ret(struct snd_soc_card *card, return ret; } + +struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, + const char *name) +{ + struct snd_card *card = soc_card->snd_card; + struct snd_kcontrol *kctl; + + if (unlikely(!name)) + return NULL; + + list_for_each_entry(kctl, &card->controls, list) + if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) + return kctl; + return NULL; +} +EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e1b65059c0c4..b6105b92f589 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2096,22 +2096,6 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev, return 0; } -struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, - const char *name) -{ - struct snd_card *card = soc_card->snd_card; - struct snd_kcontrol *kctl; - - if (unlikely(!name)) - return NULL; - - list_for_each_entry(kctl, &card->controls, list) - if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) - return kctl; - return NULL; -} -EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); - /** * snd_soc_add_component_controls - Add an array of controls to a component. * From 3359e9b6fa3eafeeb79d5f0ec8a04f3fe6986db1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:03 +0900 Subject: [PATCH 409/428] ASoC: soc-card: move snd_soc_card_jack_new() to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/878shc25kc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 3 +++ include/sound/soc.h | 4 ---- sound/soc/soc-card.c | 39 +++++++++++++++++++++++++++++++++++++++ sound/soc/soc-jack.c | 38 -------------------------------------- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index c601eddf0975..775c08d056ae 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -10,5 +10,8 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name); +int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack, + struct snd_soc_jack_pin *pins, unsigned int num_pins); #endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index f93827c6be51..38b21e815a28 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -509,10 +509,6 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw); /* Jack reporting */ -int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, - struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, - unsigned int num_pins); - void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, struct snd_soc_jack_pin *pins); diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 340ab682cc76..aa9dbb89f8a1 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -6,6 +6,7 @@ // Kuninori Morimoto // #include +#include #define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret) static inline int _soc_card_ret(struct snd_soc_card *card, @@ -40,3 +41,41 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, return NULL; } EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); + +/** + * snd_soc_card_jack_new - Create a new jack + * @card: ASoC card + * @id: an identifying string for this jack + * @type: a bitmask of enum snd_jack_type values that can be detected by + * this jack + * @jack: structure to use for the jack + * @pins: Array of jack pins to be added to the jack or NULL + * @num_pins: Number of elements in the @pins array + * + * Creates a new jack object. + * + * Returns zero if successful, or a negative error code on failure. + * On success jack will be initialised. + */ +int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack, + struct snd_soc_jack_pin *pins, unsigned int num_pins) +{ + int ret; + + mutex_init(&jack->mutex); + jack->card = card; + INIT_LIST_HEAD(&jack->pins); + INIT_LIST_HEAD(&jack->jack_zones); + BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); + + ret = snd_jack_new(card->snd_card, id, type, &jack->jack, false, false); + if (ret) + goto end; + + if (num_pins) + ret = snd_soc_jack_add_pins(jack, num_pins, pins); +end: + return soc_card_ret(card, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index b5748dcd490f..0f1820f36b4d 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -23,44 +23,6 @@ struct jack_gpio_tbl { struct snd_soc_jack_gpio *gpios; }; -/** - * snd_soc_card_jack_new - Create a new jack - * @card: ASoC card - * @id: an identifying string for this jack - * @type: a bitmask of enum snd_jack_type values that can be detected by - * this jack - * @jack: structure to use for the jack - * @pins: Array of jack pins to be added to the jack or NULL - * @num_pins: Number of elements in the @pins array - * - * Creates a new jack object. - * - * Returns zero if successful, or a negative error code on failure. - * On success jack will be initialised. - */ -int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, - struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, - unsigned int num_pins) -{ - int ret; - - mutex_init(&jack->mutex); - jack->card = card; - INIT_LIST_HEAD(&jack->pins); - INIT_LIST_HEAD(&jack->jack_zones); - BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); - - ret = snd_jack_new(card->snd_card, id, type, &jack->jack, false, false); - if (ret) - return ret; - - if (num_pins) - return snd_soc_jack_add_pins(jack, num_pins, pins); - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); - /** * snd_soc_jack_report - Report the current status for a jack * From 63efed582cc346c098adf6f5c852e2d5b0753783 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:11 +0900 Subject: [PATCH 410/428] ASoC: soc-card: move snd_soc_card_set/get_drvdata() to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/877dww25k4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 12 ++++++++++++ include/sound/soc.h | 13 ------------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 775c08d056ae..e60ad39b87bd 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -14,4 +14,16 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, unsigned int num_pins); +/* device driver data */ +static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, + void *data) +{ + card->drvdata = data; +} + +static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) +{ + return card->drvdata; +} + #endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 38b21e815a28..3072298e756a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1260,19 +1260,6 @@ struct soc_enum { #endif }; -/* device driver data */ - -static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, - void *data) -{ - card->drvdata = data; -} - -static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) -{ - return card->drvdata; -} - static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) { if (mc->reg == mc->rreg && mc->shift == mc->rshift) From 65a75718d68ea338b918328d471eff6f472192fc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:20 +0900 Subject: [PATCH 411/428] ASoC: soc-card: move snd_soc_card_get_codec_dai() to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/875zcg25jv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 14 ++++++++++++++ include/sound/soc.h | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index e60ad39b87bd..2e2dd69313d2 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -26,4 +26,18 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) return card->drvdata; } +static inline +struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, + const char *dai_name) +{ + struct snd_soc_pcm_runtime *rtd; + + for_each_card_rtds(card, rtd) { + if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) + return asoc_rtd_to_codec(rtd, 0); + } + + return NULL; +} + #endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 3072298e756a..5c126ab0e32d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1372,20 +1372,6 @@ struct snd_soc_dai *snd_soc_find_dai( #include -static inline -struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, - const char *dai_name) -{ - struct snd_soc_pcm_runtime *rtd; - - list_for_each_entry(rtd, &card->rtd_list, list) { - if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) - return asoc_rtd_to_codec(rtd, 0); - } - - return NULL; -} - static inline int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card, const char *platform_name) From bf5bb8db5bf07b0a82cdcdc44e4494e55aaa4ed7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:28 +0900 Subject: [PATCH 412/428] ASoC: soc-card: move snd_soc_card_subclass to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/874ks025jn.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 5 +++++ include/sound/soc.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 2e2dd69313d2..41bafb59eb3c 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -8,6 +8,11 @@ #ifndef __SOC_CARD_H #define __SOC_CARD_H +enum snd_soc_card_subclass { + SND_SOC_CARD_CLASS_INIT = 0, + SND_SOC_CARD_CLASS_RUNTIME = 1, +}; + struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name); int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, diff --git a/include/sound/soc.h b/include/sound/soc.h index 5c126ab0e32d..060c01c32547 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -414,11 +414,6 @@ enum snd_soc_pcm_subclass { SND_SOC_PCM_CLASS_BE = 1, }; -enum snd_soc_card_subclass { - SND_SOC_CARD_CLASS_INIT = 0, - SND_SOC_CARD_CLASS_RUNTIME = 1, -}; - int snd_soc_register_card(struct snd_soc_card *card); int snd_soc_unregister_card(struct snd_soc_card *card); int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card); From 130dc08c827db76f4a32fe7867075029fe9071d1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:39 +0900 Subject: [PATCH 413/428] ASoC: soc-card: add snd_soc_card_suspend_pre() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87367k25jc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 2 ++ sound/soc/soc-card.c | 10 ++++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 41bafb59eb3c..58b6958c0f8b 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -19,6 +19,8 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, unsigned int num_pins); +int snd_soc_card_suspend_pre(struct snd_soc_card *card); + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index aa9dbb89f8a1..710684c030bc 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -79,3 +79,13 @@ end: return soc_card_ret(card, ret); } EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); + +int snd_soc_card_suspend_pre(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->suspend_pre) + ret = card->suspend_pre(card); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b6105b92f589..52d09fa495c3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -561,8 +561,7 @@ int snd_soc_suspend(struct device *dev) snd_pcm_suspend_all(rtd->pcm); } - if (card->suspend_pre) - card->suspend_pre(card); + snd_soc_card_suspend_pre(card); /* close any waiting streams */ snd_soc_flush_all_delayed_work(card); From d17b60b2c46750ebfb6ea39a2b02d988b97484eb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:48 +0900 Subject: [PATCH 414/428] ASoC: soc-card: add snd_soc_card_suspend_post() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/871rn425j3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 10 ++++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 58b6958c0f8b..55f15120d7db 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -20,6 +20,7 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, struct snd_soc_jack_pin *pins, unsigned int num_pins); int snd_soc_card_suspend_pre(struct snd_soc_card *card); +int snd_soc_card_suspend_post(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 710684c030bc..d196103225ba 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -89,3 +89,13 @@ int snd_soc_card_suspend_pre(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_suspend_post(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->suspend_post) + ret = card->suspend_post(card); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 52d09fa495c3..c0327995efc1 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -631,8 +631,7 @@ int snd_soc_suspend(struct device *dev) } } - if (card->suspend_post) - card->suspend_post(card); + snd_soc_card_suspend_post(card); return 0; } From 934c752c38b751663fe3dc18413db13e73b8b2b2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:55 +0900 Subject: [PATCH 415/428] ASoC: soc-card: add snd_soc_card_resume_pre() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87zh9szv5k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 10 ++++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 55f15120d7db..23490df0f189 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -21,6 +21,7 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, int snd_soc_card_suspend_pre(struct snd_soc_card *card); int snd_soc_card_suspend_post(struct snd_soc_card *card); +int snd_soc_card_resume_pre(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index d196103225ba..78dc30568416 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -99,3 +99,13 @@ int snd_soc_card_suspend_post(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_resume_pre(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->resume_pre) + ret = card->resume_pre(card); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c0327995efc1..540ee055a1e8 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -660,8 +660,7 @@ static void soc_resume_deferred(struct work_struct *work) /* Bring us up into D2 so that DAPM starts enabling things */ snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); - if (card->resume_pre) - card->resume_pre(card); + snd_soc_card_resume_pre(card); for_each_card_components(card, component) { if (snd_soc_component_is_suspended(component)) From 739443d1f162ce80eb717c695e58302958b51239 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:02 +0900 Subject: [PATCH 416/428] ASoC: soc-card: add snd_soc_card_resume_post() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87y2pczv5d.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 10 ++++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 23490df0f189..ab2410397d0e 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -22,6 +22,7 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, int snd_soc_card_suspend_pre(struct snd_soc_card *card); int snd_soc_card_suspend_post(struct snd_soc_card *card); int snd_soc_card_resume_pre(struct snd_soc_card *card); +int snd_soc_card_resume_post(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 78dc30568416..dc14179a1e0f 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -109,3 +109,13 @@ int snd_soc_card_resume_pre(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_resume_post(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->resume_post) + ret = card->resume_post(card); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 540ee055a1e8..02147acf6547 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -692,8 +692,7 @@ static void soc_resume_deferred(struct work_struct *work) } } - if (card->resume_post) - card->resume_post(card); + snd_soc_card_resume_post(card); dev_dbg(card->dev, "ASoC: resume work completed\n"); From 27f07cacc9f1ddf955b85e5746f967351ab0b40b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:50:21 +0900 Subject: [PATCH 417/428] ASoC: soc-card: add probed bit field to snd_soc_card We already have bit field to control snd_soc_card. Let's add "probed" field on it instead of local variable. One note here is that soc_cleanup_card_resources() will be called as (A) formal cleanup or as (B) error handling, thus, it needs to distinguish these. In (A) case, card will have "instantiated" flag if all probe callback functions were called without error. Thus, snd_soc_unbind_card() is using it to judging card was probed. But this this patch removes it, because it is no longer needed. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87r1v4zv36.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-core.c | 18 ++++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 060c01c32547..74868436ac79 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1096,6 +1096,7 @@ struct snd_soc_card { unsigned int topology_shortname_created:1; unsigned int fully_routed:1; unsigned int disable_route_checks:1; + unsigned int probed:1; void *drvdata; }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 02147acf6547..7cfb3ee6ff4f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1723,8 +1723,7 @@ static void __soc_setup_card_name(char *name, int len, } } -static void soc_cleanup_card_resources(struct snd_soc_card *card, - int card_probed) +static void soc_cleanup_card_resources(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd, *n; @@ -1748,8 +1747,9 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card, soc_cleanup_card_debugfs(card); /* remove the card */ - if (card_probed && card->remove) + if (card->probed && card->remove) card->remove(card); + card->probed = 0; if (card->snd_card) { snd_card_free(card->snd_card); @@ -1760,12 +1760,10 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card, static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) { if (card->instantiated) { - int card_probed = 1; - card->instantiated = false; snd_soc_flush_all_delayed_work(card); - soc_cleanup_card_resources(card, card_probed); + soc_cleanup_card_resources(card); if (!unregister) list_add(&card->list, &unbind_card_list); } else { @@ -1779,7 +1777,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) struct snd_soc_pcm_runtime *rtd; struct snd_soc_component *component; struct snd_soc_dai_link *dai_link; - int ret, i, card_probed = 0; + int ret, i; mutex_lock(&client_mutex); mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); @@ -1831,7 +1829,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) ret = card->probe(card); if (ret < 0) goto probe_end; - card_probed = 1; + card->probed = 1; } /* probe all components used by DAI links on this card */ @@ -1923,7 +1921,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) goto probe_end; } } - card_probed = 1; + card->probed = 1; snd_soc_dapm_new_widgets(card); @@ -1945,7 +1943,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) probe_end: if (ret < 0) - soc_cleanup_card_resources(card, card_probed); + soc_cleanup_card_resources(card); mutex_unlock(&card->mutex); mutex_unlock(&client_mutex); From 73de4b026850da432b8bcfb73fc4af94674a8102 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:11 +0900 Subject: [PATCH 418/428] ASoC: soc-card: add snd_soc_card_probe() Card related function should be implemented at soc-card now. This patch adds it. One note here is that card has "card->probe" and "card->late_probe" callbacks. Because it needs to care "late_probe", "card->probed" flag is set under if (card->probe) at snd_soc_card_probe(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87wo4wzv54.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 2 ++ sound/soc/soc-card.c | 23 +++++++++++++++++++++++ sound/soc/soc-core.c | 9 +++------ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index ab2410397d0e..191285a0ce19 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -24,6 +24,8 @@ int snd_soc_card_suspend_post(struct snd_soc_card *card); int snd_soc_card_resume_pre(struct snd_soc_card *card); int snd_soc_card_resume_post(struct snd_soc_card *card); +int snd_soc_card_probe(struct snd_soc_card *card); + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index dc14179a1e0f..ff3bf379f166 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -119,3 +119,26 @@ int snd_soc_card_resume_post(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_probe(struct snd_soc_card *card) +{ + if (card->probe) { + int ret = card->probe(card); + + if (ret < 0) + return soc_card_ret(card, ret); + + /* + * It has "card->probe" and "card->late_probe" callbacks. + * So, set "probed" flag here, because it needs to care + * about "late_probe". + * + * see + * snd_soc_bind_card() + * snd_soc_card_late_probe() + */ + card->probed = 1; + } + + return 0; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7cfb3ee6ff4f..13a7d5158534 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1825,12 +1825,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card) goto probe_end; /* initialise the sound card only once */ - if (card->probe) { - ret = card->probe(card); - if (ret < 0) - goto probe_end; - card->probed = 1; - } + ret = snd_soc_card_probe(card); + if (ret < 0) + goto probe_end; /* probe all components used by DAI links on this card */ ret = soc_probe_link_components(card); From 5c0eac036dfd3e20dd09ab86343c3b2fb2a1ac86 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:20 +0900 Subject: [PATCH 419/428] ASoC: soc-card: add snd_soc_card_late_probe() Card related function should be implemented at soc-card now. This patch adds it. card has "card->probe" and "card->late_probe" callbacks, and "late_probe" callback is called after "probe". This means, we can set "card->probed" flag afer "late_probe" for all cases. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87v9kgzv4w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 24 ++++++++++++++++++++++++ sound/soc/soc-core.c | 12 +++--------- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 191285a0ce19..521dc05e4e9f 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -25,6 +25,7 @@ int snd_soc_card_resume_pre(struct snd_soc_card *card); int snd_soc_card_resume_post(struct snd_soc_card *card); int snd_soc_card_probe(struct snd_soc_card *card); +int snd_soc_card_late_probe(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index ff3bf379f166..317771d87e3f 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -142,3 +142,27 @@ int snd_soc_card_probe(struct snd_soc_card *card) return 0; } + +int snd_soc_card_late_probe(struct snd_soc_card *card) +{ + if (card->late_probe) { + int ret = card->late_probe(card); + + if (ret < 0) + return soc_card_ret(card, ret); + } + + /* + * It has "card->probe" and "card->late_probe" callbacks, + * and "late_probe" callback is called after "probe". + * This means, we can set "card->probed" flag afer "late_probe" + * for all cases. + * + * see + * snd_soc_bind_card() + * snd_soc_card_probe() + */ + card->probed = 1; + + return 0; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 13a7d5158534..42e8c11a0b26 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1910,15 +1910,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card) } } - if (card->late_probe) { - ret = card->late_probe(card); - if (ret < 0) { - dev_err(card->dev, "ASoC: %s late_probe() failed: %d\n", - card->name, ret); - goto probe_end; - } - } - card->probed = 1; + ret = snd_soc_card_late_probe(card); + if (ret < 0) + goto probe_end; snd_soc_dapm_new_widgets(card); From b0275d956fab05a5088e20244c8d1eb433b7b90f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:26 +0900 Subject: [PATCH 420/428] ASoC: soc-card: add snd_soc_card_remove() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87tv00zv4p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 13 +++++++++++++ sound/soc/soc-core.c | 4 +--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 521dc05e4e9f..97a34f0b0d2f 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -26,6 +26,7 @@ int snd_soc_card_resume_post(struct snd_soc_card *card); int snd_soc_card_probe(struct snd_soc_card *card); int snd_soc_card_late_probe(struct snd_soc_card *card); +int snd_soc_card_remove(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 317771d87e3f..920967a9a5ea 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -166,3 +166,16 @@ int snd_soc_card_late_probe(struct snd_soc_card *card) return 0; } + +int snd_soc_card_remove(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->probed && + card->remove) + ret = card->remove(card); + + card->probed = 0; + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 42e8c11a0b26..136ff7237a80 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1747,9 +1747,7 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card) soc_cleanup_card_debugfs(card); /* remove the card */ - if (card->probed && card->remove) - card->remove(card); - card->probed = 0; + snd_soc_card_remove(card); if (card->snd_card) { snd_card_free(card->snd_card); From 39caefda0a30cac8284264e5031a0dd478510ced Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:35 +0900 Subject: [PATCH 421/428] ASoC: soc-card: add snd_soc_card_set_bias_level() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87sgfkzv4g.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 4 ++++ sound/soc/soc-card.c | 12 ++++++++++++ sound/soc/soc-dapm.c | 3 +-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 97a34f0b0d2f..81e0c239b2e8 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -28,6 +28,10 @@ int snd_soc_card_probe(struct snd_soc_card *card); int snd_soc_card_late_probe(struct snd_soc_card *card); int snd_soc_card_remove(struct snd_soc_card *card); +int snd_soc_card_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level); + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 920967a9a5ea..dbcaa3d72dae 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -179,3 +179,15 @@ int snd_soc_card_remove(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + int ret = 0; + + if (card && card->set_bias_level) + ret = card->set_bias_level(card, dapm, level); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a4de3e4bc2ef..5dc7849ecf41 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -725,8 +725,7 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, trace_snd_soc_bias_level_start(card, level); - if (card && card->set_bias_level) - ret = card->set_bias_level(card, dapm, level); + ret = snd_soc_card_set_bias_level(card, dapm, level); if (ret != 0) goto out; From d41278ea0579a8c1e216c5321e2d207705ab3b54 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:50:35 +0900 Subject: [PATCH 422/428] ASoC: soc-card: add snd_soc_card_set_bias_level_post() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87pnaozv2s.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 3 +++ sound/soc/soc-card.c | 12 ++++++++++++ sound/soc/soc-dapm.c | 3 +-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 81e0c239b2e8..e35f777fd8cc 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -31,6 +31,9 @@ int snd_soc_card_remove(struct snd_soc_card *card); int snd_soc_card_set_bias_level(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); +int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index dbcaa3d72dae..5bc2832b3505 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -191,3 +191,15 @@ int snd_soc_card_set_bias_level(struct snd_soc_card *card, return soc_card_ret(card, ret); } + +int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + int ret = 0; + + if (card && card->set_bias_level_post) + ret = card->set_bias_level_post(card, dapm, level); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5dc7849ecf41..653a58c96e24 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -735,8 +735,7 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, if (ret != 0) goto out; - if (card && card->set_bias_level_post) - ret = card->set_bias_level_post(card, dapm, level); + ret = snd_soc_card_set_bias_level_post(card, dapm, level); out: trace_snd_soc_bias_level_done(card, level); From cbc7a6b5a87a129084c643455d16699ea490fd2f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:50:41 +0900 Subject: [PATCH 423/428] ASoC: soc-card: add snd_soc_card_add_dai_link() Card related function should be implemented at soc-card now. This patch adds it. This patch adds missing return when error case. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87o8q8zv2m.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 3 +++ sound/soc/soc-card.c | 12 ++++++++++++ sound/soc/soc-core.c | 5 +++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index e35f777fd8cc..f7e5c0ec5dc5 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -35,6 +35,9 @@ int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); +int snd_soc_card_add_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link); + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 5bc2832b3505..ba84a55fa80d 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -203,3 +203,15 @@ int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, return soc_card_ret(card, ret); } + +int snd_soc_card_add_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link) +{ + int ret = 0; + + if (card->add_dai_link) + ret = card->add_dai_link(card, dai_link); + + return soc_card_ret(card, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 136ff7237a80..d238b47252a5 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -978,8 +978,9 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, /* * Notify the machine driver for extra initialization */ - if (card->add_dai_link) - card->add_dai_link(card, dai_link); + ret = snd_soc_card_add_dai_link(card, dai_link); + if (ret < 0) + return ret; if (dai_link->ignore) return 0; From fcbbcc325bc2dd90212de19b520c190b6fbeddae Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:50:46 +0900 Subject: [PATCH 424/428] ASoC: soc-card: add snd_soc_card_remove_dai_link() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87mu5szv2h.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 2 ++ sound/soc/soc-card.c | 8 ++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index f7e5c0ec5dc5..4f2cc4fb56b7 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -37,6 +37,8 @@ int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, int snd_soc_card_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); +void snd_soc_card_remove_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index ba84a55fa80d..41c586b86dc3 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -215,3 +215,11 @@ int snd_soc_card_add_dai_link(struct snd_soc_card *card, return soc_card_ret(card, ret); } EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link); + +void snd_soc_card_remove_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link) +{ + if (card->remove_dai_link) + card->remove_dai_link(card, dai_link); +} +EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d238b47252a5..b07eca2c6ccc 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -947,8 +947,7 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, /* * Notify the machine driver for extra destruction */ - if (card->remove_dai_link) - card->remove_dai_link(card, rtd->dai_link); + snd_soc_card_remove_dai_link(card, rtd->dai_link); soc_free_pcm_runtime(rtd); } From a6b675a89e51a1cdad0481b809b7840d3f86e4b5 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 29 May 2020 21:38:23 +0000 Subject: [PATCH 425/428] ASoC: qcom: q6asm-dai: kCFI fix Fixes the following kCFI crash seen on db845c, caused by the function prototypes not matching the callback function prototype. [ 82.585661] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000001 [ 82.595387] Mem abort info: [ 82.599463] ESR = 0x96000005 [ 82.602658] EC = 0x25: DABT (current EL), IL = 32 bits [ 82.608177] SET = 0, FnV = 0 [ 82.611829] EA = 0, S1PTW = 0 [ 82.615369] Data abort info: [ 82.618751] ISV = 0, ISS = 0x00000005 [ 82.622641] CM = 0, WnR = 0 [ 82.625774] user pgtable: 4k pages, 39-bit VAs, pgdp=0000000174259000 [ 82.632292] [0000000000000001] pgd=0000000000000000, pud=0000000000000000 [ 82.639167] Internal error: Oops: 96000005 [#1] PREEMPT SMP [ 82.644795] Modules linked in: hci_uart btqca xhci_plat_hcd xhci_pci_renesas xhci_pci xhci_hcd wcn36xx wcnss_ctrl wcd934x vctrl_regulator ufs_qcom syscon_reboot_e [ 82.644927] qcom_apcs_ipc_mailbox q6asm_dai q6routing q6asm q6afe_dai q6adm q6afe q6core q6dsp_common pm8941_pwrkey pm8916_wdt platform_mhu pinctrl_spmi_mpp pine [ 82.812982] CPU: 3 PID: 240 Comm: kworker/u16:4 Tainted: G W 5.6.0-rc7-mainline-00960-g0c34353d11b9-dirty #1 [ 82.824201] Hardware name: Thundercomm Dragonboard 845c (DT) [ 82.829937] Workqueue: qcom_apr_rx apr_rxwq [apr] [ 82.834698] pstate: 80c00005 (Nzcv daif +PAN +UAO) [ 82.839553] pc : __cfi_check_fail+0x4/0x1c [q6asm_dai] [ 82.844754] lr : __cfi_check+0x3a8/0x3b0 [q6asm_dai] [ 82.849767] sp : ffffffc0105f3c20 [ 82.853123] x29: ffffffc0105f3c30 x28: 0000000000000020 [ 82.858489] x27: ffffff80f4588400 x26: ffffff80f458ec94 [ 82.863854] x25: ffffff80f458ece8 x24: ffffffe3670c7000 [ 82.869220] x23: ffffff8094bb7b34 x22: ffffffe367137000 [ 82.874585] x21: bd07909b332eada6 x20: 0000000000000001 [ 82.879950] x19: ffffffe36713863c x18: ffffff80f8df4430 [ 82.885316] x17: 0000000000000001 x16: ffffffe39d15e660 [ 82.890681] x15: 0000000000000001 x14: 0000000000000027 [ 82.896047] x13: 0000000000000000 x12: ffffffe39e6465a0 [ 82.901413] x11: 0000000000000051 x10: 000000000000ffff [ 82.906779] x9 : 000ffffffe366c19 x8 : c3c5f18762d1ceef [ 82.912145] x7 : 0000000000000000 x6 : ffffffc010877698 [ 82.917511] x5 : ffffffc0105f3c00 x4 : 0000000000000000 [ 82.922877] x3 : 0000000000000000 x2 : 0000000000000001 [ 82.928243] x1 : ffffffe36713863c x0 : 0000000000000001 [ 82.933610] Call trace: [ 82.936099] __cfi_check_fail+0x4/0x1c [q6asm_dai] [ 82.940955] q6asm_srvc_callback+0x22c/0x618 [q6asm] [ 82.945973] apr_rxwq+0x1a8/0x27c [apr] [ 82.949861] process_one_work+0x2e8/0x54c [ 82.953919] worker_thread+0x27c/0x4d4 [ 82.957715] kthread+0x144/0x154 [ 82.960985] ret_from_fork+0x10/0x18 [ 82.964603] Code: a8c37bfd f85f8e5e d65f03c0 b40000a0 (39400008) [ 82.970762] ---[ end trace 410accb839617143 ]--- [ 82.975429] Kernel panic - not syncing: Fatal exception Signed-off-by: John Stultz Reviewed-by: Srinivas Kandagatla Cc: Patrick Lai Cc: Banajit Goswami Cc: Liam Girdwood Cc: Mark Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: Srinivas Kandagatla Cc: Vinod Koul Cc: Kuninori Morimoto Cc: Stephan Gerhold Cc: Sami Tolvanen Cc: Todd Kjos Cc: Alistair Delva Cc: Amit Pundir Cc: Sumit Semwal Cc: alsa-devel@alsa-project.org Link: https://lore.kernel.org/r/20200529213823.98812-1-john.stultz@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6asm-dai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index ce77446dbbdd..aff57052a735 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -176,7 +176,7 @@ static const struct snd_compr_codec_caps q6asm_compr_caps = { }; static void event_handler(uint32_t opcode, uint32_t token, - uint32_t *payload, void *priv) + void *payload, void *priv) { struct q6asm_dai_rtd *prtd = priv; struct snd_pcm_substream *substream = prtd->substream; @@ -490,7 +490,7 @@ static int q6asm_dai_hw_params(struct snd_soc_component *component, } static void compress_event_handler(uint32_t opcode, uint32_t token, - uint32_t *payload, void *priv) + void *payload, void *priv) { struct q6asm_dai_rtd *prtd = priv; struct snd_compr_stream *substream = prtd->cstream; From 7fccfecf24fd1248c619e2cd7d55916327bf8dc1 Mon Sep 17 00:00:00 2001 From: Dmitry Panchenko Date: Mon, 1 Jun 2020 13:22:24 +0300 Subject: [PATCH 426/428] ALSA: usb-audio: Add Pioneer DJ DJM-900NXS2 support Pioneer DJ DJM-900NXS2 is a widely used DJ mixer with 2 audio USB interfaces. Both have a MIDI controller, 10 playback and 12 capture channels. Audio endpoints are vendor-specific and 3 files need to be patched. All playback and capture channels work fine with all supported sample rates (44.1k, 48k, 96k). Patches are attached. Signed-off-by: Dmitry Panchenko Link: https://lore.kernel.org/r/48ab19ff-3303-9bf8-ed0e-bcb31d8537eb@d-systems.ee Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 4 +++ sound/usb/quirks-table.h | 63 ++++++++++++++++++++++++++++++++++++++++ sound/usb/quirks.c | 27 +++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index d61c2f1095b5..8a05dcb1344f 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -370,6 +370,10 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, ep = 0x81; ifnum = 2; goto add_sync_ep_from_ifnum; + case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */ + ep = 0x82; + ifnum = 0; + goto add_sync_ep_from_ifnum; case USB_ID(0x0582, 0x01d8): /* BOSS Katana */ /* BOSS Katana amplifiers do not need quirks */ return 0; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 5236f4d015c4..6d6492195bdc 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3557,5 +3557,68 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */ QUIRK_DEVICE_PROFILE("Gigabyte", "Aorus Master Main Audio", "Gigabyte-Aorus-Master-Main-Audio") }, +{ + /* + * Pioneer DJ DJM-900NXS2 + * 10 channels playback & 12 channels capture @ 44.1/48/96kHz S24LE + */ + USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000a), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 10, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000| + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 44100, 48000, 96000 + } + } + }, + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 12, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x82, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC| + USB_ENDPOINT_USAGE_IMPLICIT_FB, + .rates = SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000| + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 44100, 48000, 96000 + } + } + }, + { + .ifnum = -1 + } + } + } +}, #undef USB_DEVICE_VENDOR_SPEC diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index c0e3bc4afec6..bca0179a0ef8 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1458,6 +1458,30 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs, subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0; } + +/* + * Pioneer DJ DJM-900NXS2 + * Device needs to know the sample rate each time substream is started + */ +static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs) +{ + + /* Convert sample rate value to little endian */ + u8 sr[3]; + + sr[0] = subs->cur_rate & 0xff; + sr[1] = (subs->cur_rate >> 8) & 0xff; + sr[2] = (subs->cur_rate >> 16) & 0xff; + + /* Configure device */ + usb_set_interface(subs->dev, 0, 1); + snd_usb_ctl_msg(subs->stream->chip->dev, + usb_rcvctrlpipe(subs->stream->chip->dev, 0), + 0x01, 0x22, 0x0100, 0x0082, &sr, 0x0003); + + return 0; +} + void snd_usb_set_format_quirk(struct snd_usb_substream *subs, struct audioformat *fmt) { @@ -1468,6 +1492,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */ set_format_emu_quirk(subs, fmt); break; + case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */ + pioneer_djm_set_format_quirk(subs); + break; } } From 27a7c67012cfa6d79f87fbb51afa13c6c0e24e34 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 2 Jun 2020 21:31:37 -0400 Subject: [PATCH 427/428] ALSA: hda: add sienna_cichlid audio asic id for sienna_cichlid up dp/hdmi ati hda is not shown in audio settings [ rearranged to a more appropriate place per device number order -- tiwai ] Signed-off-by: Hersen Wu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: Link: https://lore.kernel.org/r/20200603013137.1849404-1-alexander.deucher@amd.com 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 0310193ea1bd..41a03c61a74b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2662,6 +2662,9 @@ static const struct pci_device_id azx_ids[] = { { PCI_DEVICE(0x1002, 0xab20), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xab28), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, { PCI_DEVICE(0x1002, 0xab38), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | AZX_DCAPS_PM_RUNTIME }, From d9b8fbf15d05350b36081eddafcf7b15aa1add50 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 3 Jun 2020 17:24:59 +0800 Subject: [PATCH 428/428] ALSA: es1688: Add the missed snd_card_free() snd_es968_pnp_detect() misses a snd_card_free() in a failed path. Add the missed function call to fix it. Fixes: a20971b201ac ("ALSA: Merge es1688 and es968 drivers") Signed-off-by: Chuhong Yuan Cc: Link: https://lore.kernel.org/r/20200603092459.1424093-1-hslester96@gmail.com Signed-off-by: Takashi Iwai --- sound/isa/es1688/es1688.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index ff3a05ad99c0..64610571a5e1 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -267,8 +267,10 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard, return error; } error = snd_es1688_probe(card, dev); - if (error < 0) + if (error < 0) { + snd_card_free(card); return error; + } pnp_set_card_drvdata(pcard, card); snd_es968_pnp_is_probed = 1; return 0;