diff options
26 files changed, 160 insertions, 95 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index cc1d18cb5d18..db0f6be56dd4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4021,8 +4021,8 @@ F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml F: sound/soc/codecs/cros_ec_codec.* CIRRUS LOGIC AUDIO CODEC DRIVERS -M: Brian Austin <brian.austin@cirrus.com> -M: Paul Handrigan <Paul.Handrigan@cirrus.com> +M: James Schulman <james.schulman@cirrus.com> +M: David Rhodes <david.rhodes@cirrus.com> L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: sound/soc/codecs/cs* @@ -15613,6 +15613,17 @@ F: sound/soc/ F: include/dt-bindings/sound/ F: include/sound/soc* +SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS +M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> +M: Liam Girdwood <lgirdwood@gmail.com> +M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> +M: Kai Vehmanen <kai.vehmanen@linux.intel.com> +M: Daniel Baluta <daniel.baluta@nxp.com> +L: sound-open-firmware@alsa-project.org (moderated for non-subscribers) +W: https://github.com/thesofproject/linux/ +S: Supported +F: sound/soc/sof/ + SOUNDWIRE SUBSYSTEM M: Vinod Koul <vkoul@kernel.org> M: Sanyog Kale <sanyog.r.kale@intel.com> diff --git a/include/sound/soc.h b/include/sound/soc.h index 8a2266676b2d..efb8bad7b0fa 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1058,6 +1058,7 @@ struct snd_soc_card { 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; diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index 16313b973eaa..eb3d8255ea6c 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -135,6 +135,7 @@ MODULE_DEVICE_TABLE(of, max98357a_device_id); #ifdef CONFIG_ACPI static const struct acpi_device_id max98357a_acpi_match[] = { { "MX98357A", 0 }, + { "MX98360A", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, max98357a_acpi_match); diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index ae6f6121bc1b..3e0b5c43ece8 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -1146,7 +1146,7 @@ static void rt5682_jack_detect_handler(struct work_struct *work) static const struct snd_kcontrol_new rt5682_snd_controls[] = { /* DAC Digital Volume */ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5682_DAC1_DIG_VOL, - RT5682_L_VOL_SFT + 1, RT5682_R_VOL_SFT + 1, 86, 0, dac_vol_tlv), + RT5682_L_VOL_SFT + 1, RT5682_R_VOL_SFT + 1, 87, 0, dac_vol_tlv), /* IN Boost Volume */ SOC_SINGLE_TLV("CBJ Boost Volume", RT5682_CBJ_BST_CTRL, @@ -2651,6 +2651,8 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, 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); diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 18faaa2a49a0..fc99e7484283 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -651,6 +651,8 @@ #define RT5682_DMIC_1_EN_SFT 15 #define RT5682_DMIC_1_DIS (0x0 << 15) #define RT5682_DMIC_1_EN (0x1 << 15) +#define RT5682_FIFO_CLK_DIV_MASK (0x7 << 12) +#define RT5682_FIFO_CLK_DIV_2 (0x1 << 12) #define RT5682_DMIC_1_DP_MASK (0x3 << 4) #define RT5682_DMIC_1_DP_SFT 4 #define RT5682_DMIC_1_DP_GPIO2 (0x0 << 4) diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index be52886a5edb..fb2233ca9103 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -409,7 +409,7 @@ static const struct snd_kcontrol_new vsense_switch = 1, 1); static const struct snd_kcontrol_new tas2562_snd_controls[] = { - SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 0, 0x1c, 0, + SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 1, 0x1c, 0, tas2562_dac_tlv), }; diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index f11ffa28683b..700cc1212770 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -4926,11 +4926,11 @@ static const struct regmap_range_cfg wcd9335_ranges[] = { .name = "WCD9335", .range_min = 0x0, .range_max = WCD9335_MAX_REGISTER, - .selector_reg = WCD9335_REG(0x0, 0), + .selector_reg = WCD9335_SEL_REGISTER, .selector_mask = 0xff, .selector_shift = 0, - .window_start = 0x0, - .window_len = 0x1000, + .window_start = 0x800, + .window_len = 0x100, }, }; @@ -4968,12 +4968,12 @@ static const struct regmap_range_cfg wcd9335_ifc_ranges[] = { { .name = "WCD9335-IFC-DEV", .range_min = 0x0, - .range_max = WCD9335_REG(0, 0x7ff), - .selector_reg = WCD9335_REG(0, 0x0), - .selector_mask = 0xff, + .range_max = WCD9335_MAX_REGISTER, + .selector_reg = WCD9335_SEL_REGISTER, + .selector_mask = 0xfff, .selector_shift = 0, - .window_start = 0x0, - .window_len = 0x1000, + .window_start = 0x800, + .window_len = 0x400, }, }; @@ -4981,7 +4981,7 @@ static struct regmap_config wcd9335_ifc_regmap_config = { .reg_bits = 16, .val_bits = 8, .can_multi_write = true, - .max_register = WCD9335_REG(0, 0x7FF), + .max_register = WCD9335_MAX_REGISTER, .ranges = wcd9335_ifc_ranges, .num_ranges = ARRAY_SIZE(wcd9335_ifc_ranges), }; diff --git a/sound/soc/codecs/wcd9335.h b/sound/soc/codecs/wcd9335.h index 4d9be2496c30..72060824c743 100644 --- a/sound/soc/codecs/wcd9335.h +++ b/sound/soc/codecs/wcd9335.h @@ -8,9 +8,9 @@ * in slimbus mode the reg base starts from 0x800 * in i2s/i2c mode the reg base is 0x0 */ -#define WCD9335_REG(pg, r) ((pg << 12) | (r) | 0x800) +#define WCD9335_REG(pg, r) ((pg << 8) | (r)) #define WCD9335_REG_OFFSET(r) (r & 0xFF) -#define WCD9335_PAGE_OFFSET(r) ((r >> 12) & 0xFF) +#define WCD9335_PAGE_OFFSET(r) ((r >> 8) & 0xFF) /* Page-0 Registers */ #define WCD9335_PAGE0_PAGE_REGISTER WCD9335_REG(0x00, 0x000) @@ -600,7 +600,8 @@ #define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_ENABLE BIT(0) #define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_DISABLE 0 #define WCD9335_CDC_TOP_TOP_CFG1 WCD9335_REG(0x0d, 0x082) -#define WCD9335_MAX_REGISTER WCD9335_REG(0x80, 0x0FF) +#define WCD9335_MAX_REGISTER 0xffff +#define WCD9335_SEL_REGISTER 0x800 /* SLIMBUS Slave Registers */ #define WCD9335_SLIM_PGD_PORT_INT_EN0 WCD9335_REG(0, 0x30) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index d3d32b501aca..ffb9836e0538 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1436,12 +1436,12 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, subname = NULL; /* don't append subname */ break; case 2: - ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, + ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s%c %.12s %x", dsp->name, *region_name, wm_adsp_fw_text[dsp->fw], alg_region->alg); break; default: - ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, + ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %.12s %x", dsp->name, wm_adsp_fw_text[dsp->fw], alg_region->alg); break; diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index b59f1d0e7f84..25776aa64d74 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1150,7 +1150,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, wsa881x->sconfig.type = SDW_STREAM_PDM; pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0); pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; - gpiod_set_value(wsa881x->sd_n, 1); + gpiod_direction_output(wsa881x->sd_n, 1); wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config); if (IS_ERR(wsa881x->regmap)) { diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index 1a302436d450..6cff603d4656 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -226,9 +226,6 @@ SND_SOC_DAILINK_DEF(be, #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#else -SND_SOC_DAILINK_DEF(ssp0_port, - DAILINK_COMP_ARRAY(COMP_DUMMY())); #endif static struct snd_soc_dai_link bdw_rt5650_dais[] = { @@ -264,7 +261,11 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = bdw_rt5650_init, +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) + SND_SOC_DAILINK_REG(dummy, be, dummy), +#else SND_SOC_DAILINK_REG(ssp0_port, be, platform), +#endif }, }; diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index bb643c99069d..63108e1a0e4d 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -298,9 +298,6 @@ SND_SOC_DAILINK_DEF(be, #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#else -SND_SOC_DAILINK_DEF(ssp0_port, - DAILINK_COMP_ARRAY(COMP_DUMMY())); #endif /* Wake on voice interface */ @@ -350,7 +347,11 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = bdw_rt5677_init, +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) + SND_SOC_DAILINK_REG(dummy, be, dummy), +#else SND_SOC_DAILINK_REG(ssp0_port, be, platform), +#endif }, }; diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index b9c12e24c70b..ffbb597052aa 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -167,9 +167,6 @@ SND_SOC_DAILINK_DEF(codec, #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#else -SND_SOC_DAILINK_DEF(ssp0_port, - DAILINK_COMP_ARRAY(COMP_DUMMY())); #endif /* broadwell digital audio interface glue - connects codec <--> CPU */ @@ -226,7 +223,11 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { .ops = &broadwell_rt286_ops, .dpcm_playback = 1, .dpcm_capture = 1, +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) + SND_SOC_DAILINK_REG(dummy, codec, dummy), +#else SND_SOC_DAILINK_REG(ssp0_port, codec, platform), +#endif }, }; diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index c99c8b23e509..b3b835156d77 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -686,6 +686,7 @@ static struct snd_soc_card skylake_audio_card = { .codec_conf = ssm4567_codec_conf, .num_configs = ARRAY_SIZE(ssm4567_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = skylake_card_late_probe, }; diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 92a82e6b5fe6..38b9d7494083 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -17,7 +17,6 @@ #include "skl.h" #define BXT_BASEFW_TIMEOUT 3000 -#define BXT_INIT_TIMEOUT 300 #define BXT_ROM_INIT_TIMEOUT 70 #define BXT_IPC_PURGE_FW 0x01004000 @@ -38,8 +37,6 @@ /* Delay before scheduling D0i3 entry */ #define BXT_D0I3_DELAY 5000 -#define BXT_FW_ROM_INIT_RETRY 3 - static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) { return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index 4f64f097e9ae..c6abcd5aa67b 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -57,18 +57,34 @@ static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) ctx->dsp_ops.stream_tag = stream_tag; memcpy(ctx->dmab.area, fwdata, fwsize); + ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK); + if (ret < 0) { + dev_err(ctx->dev, "dsp core0 power up failed\n"); + ret = -EIO; + goto base_fw_load_failed; + } + /* purge FW request */ sst_dsp_shim_write(ctx, CNL_ADSP_REG_HIPCIDR, CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE | ((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID))); - ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); + ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); if (ret < 0) { - dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret); + dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret); ret = -EIO; goto base_fw_load_failed; } + ret = sst_dsp_register_poll(ctx, CNL_ADSP_REG_HIPCIDA, + CNL_ADSP_REG_HIPCIDA_DONE, + CNL_ADSP_REG_HIPCIDA_DONE, + BXT_INIT_TIMEOUT, "HIPCIDA Done"); + if (ret < 0) { + dev_err(ctx->dev, "timeout for purge request: %d\n", ret); + goto base_fw_load_failed; + } + /* enable interrupt */ cnl_ipc_int_enable(ctx); cnl_ipc_op_int_enable(ctx); @@ -109,7 +125,7 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx) { struct firmware stripped_fw; struct skl_dev *cnl = ctx->thread_context; - int ret; + int ret, i; if (!ctx->fw) { ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); @@ -131,12 +147,16 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx) stripped_fw.size = ctx->fw->size; skl_dsp_strip_extended_manifest(&stripped_fw); - ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); - if (ret < 0) { - dev_err(ctx->dev, "prepare firmware failed: %d\n", ret); - goto cnl_load_base_firmware_failed; + for (i = 0; i < BXT_FW_ROM_INIT_RETRY; i++) { + ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); + if (!ret) + break; + dev_dbg(ctx->dev, "prepare firmware failed: %d\n", ret); } + if (ret < 0) + goto cnl_load_base_firmware_failed; + ret = sst_transfer_fw_host_dma(ctx); if (ret < 0) { dev_err(ctx->dev, "transfer firmware failed: %d\n", ret); @@ -158,6 +178,7 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx) return 0; cnl_load_base_firmware_failed: + dev_err(ctx->dev, "firmware load failed: %d\n", ret); release_firmware(ctx->fw); ctx->fw = NULL; diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index 19f328d71f24..d9c8f5cb389e 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -182,7 +182,8 @@ void skl_nhlt_remove_sysfs(struct skl_dev *skl) { struct device *dev = &skl->pci->dev; - sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); + if (skl->nhlt) + sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); } /* diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index cdfec0fca577..1df9ef422f61 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -67,6 +67,8 @@ struct skl_dev; #define SKL_FW_INIT 0x1 #define SKL_FW_RFW_START 0xf +#define BXT_FW_ROM_INIT_RETRY 3 +#define BXT_INIT_TIMEOUT 300 #define SKL_ADSPIC_IPC 1 #define SKL_ADSPIS_IPC 1 diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index f755ca2484cf..7ad8a75759bd 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -130,6 +130,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) struct hdac_ext_link *hlink; int ret; + snd_hdac_set_codec_wakeup(bus, true); skl_enable_miscbdcge(bus->dev, false); ret = snd_hdac_bus_init_chip(bus, full_reset); @@ -138,6 +139,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); skl_enable_miscbdcge(bus->dev, true); + snd_hdac_set_codec_wakeup(bus, false); return ret; } @@ -481,13 +483,8 @@ static struct skl_ssp_clk skl_ssp_clks[] = { static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl_dev *skl, struct snd_soc_acpi_mach *machines) { - struct hdac_bus *bus = skl_to_bus(skl); struct snd_soc_acpi_mach *mach; - /* check if we have any codecs detected on bus */ - if (bus->codec_mask == 0) - return NULL; - /* point to common table */ mach = snd_soc_acpi_intel_hda_machines; @@ -636,6 +633,9 @@ static int skl_clock_device_register(struct skl_dev *skl) struct platform_device_info pdevinfo = {NULL}; struct skl_clk_pdata *clk_pdata; + if (!skl->nhlt) + return 0; + clk_pdata = devm_kzalloc(&skl->pci->dev, sizeof(*clk_pdata), GFP_KERNEL); if (!clk_pdata) @@ -803,6 +803,9 @@ static void skl_probe_work(struct work_struct *work) return; } + skl_init_pci(skl); + skl_dum_set(bus); + err = skl_init_chip(bus, true); if (err < 0) { dev_err(bus->dev, "Init chip failed with err: %d\n", err); @@ -918,8 +921,6 @@ static int skl_first_init(struct hdac_bus *bus) return -ENXIO; } - snd_hdac_bus_reset_link(bus, true); - snd_hdac_bus_parse_capabilities(bus); /* check if PPCAP exists */ @@ -967,11 +968,7 @@ static int skl_first_init(struct hdac_bus *bus) if (err < 0) return err; - /* initialize chip */ - skl_init_pci(skl); - skl_dum_set(bus); - - return skl_init_chip(bus, true); + return 0; } static int skl_probe(struct pci_dev *pci, @@ -1064,8 +1061,6 @@ static int skl_probe(struct pci_dev *pci, if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(bus); - snd_hdac_bus_stop_chip(bus); - /* create device for soc dmic */ err = skl_dmic_device_register(skl); if (err < 0) { @@ -1082,7 +1077,8 @@ out_dsp_free: out_clk_free: skl_clock_device_unregister(skl); out_nhlt_free: - intel_nhlt_free(skl->nhlt); + if (skl->nhlt) + intel_nhlt_free(skl->nhlt); out_free: skl_free(bus); @@ -1131,7 +1127,8 @@ static void skl_remove(struct pci_dev *pci) skl_dmic_device_unregister(skl); skl_clock_device_unregister(skl); skl_nhlt_remove_sysfs(skl); - intel_nhlt_free(skl->nhlt); + if (skl->nhlt) + intel_nhlt_free(skl->nhlt); skl_free(bus); dev_set_drvdata(&pci->dev, NULL); } diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 9d5405881209..434737b2b2b2 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -83,7 +83,7 @@ #define JZ_AIC_I2S_STATUS_BUSY BIT(2) #define JZ_AIC_CLK_DIV_MASK 0xf -#define I2SDIV_DV_SHIFT 8 +#define I2SDIV_DV_SHIFT 0 #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) #define I2SDIV_IDV_SHIFT 8 #define I2SDIV_IDV_MASK (0xf << I2SDIV_IDV_SHIFT) diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index c0d422d0ab94..8b48815ff918 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -69,6 +69,8 @@ struct q6asm_dai_rtd { }; struct q6asm_dai_data { + struct snd_soc_dai_driver *dais; + int num_dais; long long int sid; }; @@ -889,7 +891,7 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = { .compr_ops = &q6asm_dai_compr_ops, }; -static struct snd_soc_dai_driver q6asm_fe_dais[] = { +static struct snd_soc_dai_driver q6asm_fe_dais_template[] = { Q6ASM_FEDAI_DRIVER(1), Q6ASM_FEDAI_DRIVER(2), Q6ASM_FEDAI_DRIVER(3), @@ -903,10 +905,22 @@ static struct snd_soc_dai_driver q6asm_fe_dais[] = { static int of_q6asm_parse_dai_data(struct device *dev, struct q6asm_dai_data *pdata) { - static struct snd_soc_dai_driver *dai_drv; + struct snd_soc_dai_driver *dai_drv; struct snd_soc_pcm_stream empty_stream; struct device_node *node; - int ret, id, dir; + int ret, id, dir, idx = 0; + + + pdata->num_dais = of_get_child_count(dev->of_node); + if (!pdata->num_dais) { + dev_err(dev, "No dais found in DT\n"); + return -EINVAL; + } + + pdata->dais = devm_kcalloc(dev, pdata->num_dais, sizeof(*dai_drv), + GFP_KERNEL); + if (!pdata->dais) + return -ENOMEM; memset(&empty_stream, 0, sizeof(empty_stream)); @@ -917,7 +931,8 @@ static int of_q6asm_parse_dai_data(struct device *dev, continue; } - dai_drv = &q6asm_fe_dais[id]; + dai_drv = &pdata->dais[idx++]; + *dai_drv = q6asm_fe_dais_template[id]; ret = of_property_read_u32(node, "direction", &dir); if (ret) @@ -955,11 +970,12 @@ static int q6asm_dai_probe(struct platform_device *pdev) dev_set_drvdata(dev, pdata); - of_q6asm_parse_dai_data(dev, pdata); + rc = of_q6asm_parse_dai_data(dev, pdata); + if (rc) + return rc; return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component, - q6asm_fe_dais, - ARRAY_SIZE(q6asm_fe_dais)); + pdata->dais, pdata->num_dais); } static const struct of_device_id q6asm_dai_device_id[] = { diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 20724102e85a..4d5915b9a06d 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -918,25 +918,6 @@ static const struct snd_soc_dapm_route intercon[] = { {"MM_UL6", NULL, "MultiMedia6 Mixer"}, {"MM_UL7", NULL, "MultiMedia7 Mixer"}, {"MM_UL8", NULL, "MultiMedia8 Mixer"}, - - {"MM_DL1", NULL, "MultiMedia1 Playback" }, - {"MM_DL2", NULL, "MultiMedia2 Playback" }, - {"MM_DL3", NULL, "MultiMedia3 Playback" }, - {"MM_DL4", NULL, "MultiMedia4 Playback" }, - {"MM_DL5", NULL, "MultiMedia5 Playback" }, - {"MM_DL6", NULL, "MultiMedia6 Playback" }, - {"MM_DL7", NULL, "MultiMedia7 Playback" }, - {"MM_DL8", NULL, "MultiMedia8 Playback" }, - - {"MultiMedia1 Capture", NULL, "MM_UL1"}, - {"MultiMedia2 Capture", NULL, "MM_UL2"}, - {"MultiMedia3 Capture", NULL, "MM_UL3"}, - {"MultiMedia4 Capture", NULL, "MM_UL4"}, - {"MultiMedia5 Capture", NULL, "MM_UL5"}, - {"MultiMedia6 Capture", NULL, "MM_UL6"}, - {"MultiMedia7 Capture", NULL, "MM_UL7"}, - {"MultiMedia8 Capture", NULL, "MM_UL8"}, - }; static int routing_hw_params(struct snd_soc_component *component, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 068d809c349a..b17366bac846 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1256,8 +1256,18 @@ static int soc_probe_component(struct snd_soc_card *card, ret = snd_soc_dapm_add_routes(dapm, component->driver->dapm_routes, component->driver->num_dapm_routes); - if (ret < 0) - goto err_probe; + if (ret < 0) { + if (card->disable_route_checks) { + dev_info(card->dev, + "%s: disable_route_checks set, ignoring errors on add_routes\n", + __func__); + } else { + dev_err(card->dev, + "%s: snd_soc_dapm_add_routes failed: %d\n", + __func__, ret); + goto err_probe; + } + } /* see for_each_card_components */ list_add(&component->card_list, &card->component_dev_list); @@ -1938,8 +1948,18 @@ static int snd_soc_bind_card(struct snd_soc_card *card) ret = snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, card->num_dapm_routes); - if (ret < 0) - goto probe_end; + if (ret < 0) { + if (card->disable_route_checks) { + dev_info(card->dev, + "%s: disable_route_checks set, ignoring errors on add_routes\n", + __func__); + } else { + dev_err(card->dev, + "%s: snd_soc_dapm_add_routes failed: %d\n", + __func__, ret); + goto probe_end; + } + } ret = snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, card->num_of_dapm_routes); diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 575da6aba807..66958c57d884 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -251,7 +251,7 @@ static int soc_tplg_vendor_load_(struct soc_tplg *tplg, { int ret = 0; - if (tplg->comp && tplg->ops && tplg->ops->vendor_load) + if (tplg->ops && tplg->ops->vendor_load) ret = tplg->ops->vendor_load(tplg->comp, tplg->index, hdr); else { dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n", @@ -283,7 +283,7 @@ static int soc_tplg_vendor_load(struct soc_tplg *tplg, static int soc_tplg_widget_load(struct soc_tplg *tplg, struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w) { - if (tplg->comp && tplg->ops && tplg->ops->widget_load) + if (tplg->ops && tplg->ops->widget_load) return tplg->ops->widget_load(tplg->comp, tplg->index, w, tplg_w); @@ -295,7 +295,7 @@ static int soc_tplg_widget_load(struct soc_tplg *tplg, static int soc_tplg_widget_ready(struct soc_tplg *tplg, struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w) { - if (tplg->comp && tplg->ops && tplg->ops->widget_ready) + if (tplg->ops && tplg->ops->widget_ready) return tplg->ops->widget_ready(tplg->comp, tplg->index, w, tplg_w); @@ -307,7 +307,7 @@ static int soc_tplg_dai_load(struct soc_tplg *tplg, struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai) { - if (tplg->comp && tplg->ops && tplg->ops->dai_load) + if (tplg->ops && tplg->ops->dai_load) return tplg->ops->dai_load(tplg->comp, tplg->index, dai_drv, pcm, dai); @@ -318,7 +318,7 @@ static int soc_tplg_dai_load(struct soc_tplg *tplg, static int soc_tplg_dai_link_load(struct soc_tplg *tplg, struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg) { - if (tplg->comp && tplg->ops && tplg->ops->link_load) + if (tplg->ops && tplg->ops->link_load) return tplg->ops->link_load(tplg->comp, tplg->index, link, cfg); return 0; @@ -327,7 +327,7 @@ static int soc_tplg_dai_link_load(struct soc_tplg *tplg, /* tell the component driver that all firmware has been loaded in this request */ static void soc_tplg_complete(struct soc_tplg *tplg) { - if (tplg->comp && tplg->ops && tplg->ops->complete) + if (tplg->ops && tplg->ops->complete) tplg->ops->complete(tplg->comp); } @@ -684,7 +684,7 @@ EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_bind_event); static int soc_tplg_init_kcontrol(struct soc_tplg *tplg, struct snd_kcontrol_new *k, struct snd_soc_tplg_ctl_hdr *hdr) { - if (tplg->comp && tplg->ops && tplg->ops->control_load) + if (tplg->ops && tplg->ops->control_load) return tplg->ops->control_load(tplg->comp, tplg->index, k, hdr); @@ -1174,7 +1174,7 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, static int soc_tplg_add_route(struct soc_tplg *tplg, struct snd_soc_dapm_route *route) { - if (tplg->comp && tplg->ops && tplg->ops->dapm_route_load) + if (tplg->ops && tplg->ops->dapm_route_load) return tplg->ops->dapm_route_load(tplg->comp, tplg->index, route); @@ -2564,7 +2564,7 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, } /* pass control to component driver for optional further init */ - if (tplg->comp && tplg->ops && tplg->ops->manifest) + if (tplg->ops && tplg->ops->manifest) ret = tplg->ops->manifest(tplg->comp, tplg->index, _manifest); if (!abi_match) /* free the duplicated one */ @@ -2736,6 +2736,10 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp, struct soc_tplg tplg; int ret; + /* component needs to exist to keep and reference data while parsing */ + if (!comp) + return -EINVAL; + /* setup parsing context */ memset(&tplg, 0, sizeof(tplg)); tplg.fw = fw; diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index c0ab9bb2a797..d2234f802788 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -547,6 +547,8 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, SOF_HDA_REG_PP_PPCTL, mask, 0); spin_unlock_irq(&bus->reg_lock); + stream->substream = NULL; + return 0; } diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index 3769d9ce5dbe..e6e75897cce8 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -1009,6 +1009,8 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) if (idr == SPDIFRX_IPIDR_NUMBER) { ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_VERR, &ver); + if (ret) + goto error; dev_dbg(&pdev->dev, "SPDIFRX version: %lu.%lu registered\n", FIELD_GET(SPDIFRX_VERR_MAJ_MASK, ver), |