diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/amd/ps/pci-ps.c | 17 | ||||
-rw-r--r-- | sound/soc/amd/yc/acp6x-mach.c | 13 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/codecs/cs42l43.c | 1 | ||||
-rw-r--r-- | sound/soc/codecs/es8316.c | 10 | ||||
-rw-r--r-- | sound/soc/codecs/es8326.c | 23 | ||||
-rw-r--r-- | sound/soc/codecs/rt722-sdca.c | 7 | ||||
-rw-r--r-- | sound/soc/codecs/tas2781-i2c.c | 4 | ||||
-rw-r--r-- | sound/soc/fsl/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_spdif.c | 2 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_xcvr.c | 2 | ||||
-rw-r--r-- | sound/soc/generic/audio-graph-card2.c | 2 | ||||
-rw-r--r-- | sound/soc/intel/avs/boards/da7219.c | 17 | ||||
-rw-r--r-- | sound/soc/intel/boards/sof_sdw.c | 31 | ||||
-rw-r--r-- | sound/soc/mediatek/common/mtk-afe-platform-driver.c | 4 | ||||
-rw-r--r-- | sound/soc/mediatek/mt8188/mt8188-mt6359.c | 4 | ||||
-rw-r--r-- | sound/soc/renesas/rcar/adg.c | 28 | ||||
-rw-r--r-- | sound/soc/renesas/rcar/core.c | 4 | ||||
-rw-r--r-- | sound/soc/renesas/rcar/rsnd.h | 2 | ||||
-rw-r--r-- | sound/soc/samsung/Kconfig | 6 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-dai.c | 25 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda.h | 2 | ||||
-rw-r--r-- | sound/soc/sof/ipc3-topology.c | 7 |
23 files changed, 148 insertions, 66 deletions
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 823a69bf778b..4575326d0635 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -375,11 +375,18 @@ static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *a { struct acpi_device *pdm_dev; const union acpi_object *obj; + acpi_handle handle; + acpi_integer dmic_status; u32 config; bool is_dmic_dev = false; bool is_sdw_dev = false; + bool wov_en, dmic_en; int ret; + /* IF WOV entry not found, enable dmic based on acp-audio-device-type entry*/ + wov_en = true; + dmic_en = false; + config = readl(acp_data->acp63_base + ACP_PIN_CONFIG); switch (config) { case ACP_CONFIG_4: @@ -412,10 +419,18 @@ static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *a if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type", ACPI_TYPE_INTEGER, &obj) && obj->integer.value == ACP_DMIC_DEV) - is_dmic_dev = true; + dmic_en = true; } + + handle = ACPI_HANDLE(&pci->dev); + ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); + if (!ACPI_FAILURE(ret)) + wov_en = dmic_status; } + if (dmic_en && wov_en) + is_dmic_dev = true; + if (acp_data->is_sdw_config) { ret = acp_scan_sdw_devices(&pci->dev, ACP63_SDW_ADDR); if (!ret && acp_data->info.link_mask) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index e38c5885dadf..ecf57a6cb7c3 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -578,14 +578,19 @@ static int acp6x_probe(struct platform_device *pdev) handle = ACPI_HANDLE(pdev->dev.parent); ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); - if (!ACPI_FAILURE(ret)) + if (!ACPI_FAILURE(ret)) { wov_en = dmic_status; + if (!wov_en) + return -ENODEV; + } else { + /* Incase of ACPI method read failure then jump to check_dmi_entry */ + goto check_dmi_entry; + } - if (is_dmic_enable && wov_en) + if (is_dmic_enable) platform_set_drvdata(pdev, &acp6x_card); - else - return 0; +check_dmi_entry: /* check for any DMI overrides */ dmi_id = dmi_first_match(yc_acp_quirk_table); if (dmi_id) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0f2df7c91e18..0b9e87dc2b6c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2451,6 +2451,7 @@ config SND_SOC_WM8993 config SND_SOC_WM8994 tristate + depends on MFD_WM8994 config SND_SOC_WM8995 tristate diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c index 4236f78beec0..83c21c17fb80 100644 --- a/sound/soc/codecs/cs42l43.c +++ b/sound/soc/codecs/cs42l43.c @@ -2404,6 +2404,7 @@ static int cs42l43_codec_runtime_resume(struct device *dev) static const struct dev_pm_ops cs42l43_codec_pm_ops = { RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct platform_device_id cs42l43_codec_id_table[] = { diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 61729e5b50a8..f508df01145b 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -39,7 +39,9 @@ struct es8316_priv { struct snd_soc_jack *jack; int irq; unsigned int sysclk; - unsigned int allowed_rates[ARRAY_SIZE(supported_mclk_lrck_ratios)]; + /* ES83xx supports halving the MCLK so it supports twice as many rates + */ + unsigned int allowed_rates[ARRAY_SIZE(supported_mclk_lrck_ratios) * 2]; struct snd_pcm_hw_constraint_list sysclk_constraints; bool jd_inverted; }; @@ -386,6 +388,12 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, if (freq % ratio == 0) es8316->allowed_rates[count++] = freq / ratio; + + /* We also check if the halved MCLK produces a valid rate + * since the codec supports halving the MCLK. + */ + if ((freq / ratio) % 2 == 0) + es8316->allowed_rates[count++] = freq / ratio / 2; } if (count) { diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index a5603b617688..b06eead7e0f6 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -616,7 +616,7 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) 0x0F, 0x0F); if (es8326->version > ES8326_VERSION_B) { regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); - regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x10); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x30); } } } else { @@ -631,6 +631,8 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) regmap_write(es8326->regmap, ES8326_HPR_OFFSET_INI, offset_r); es8326->calibrated = true; } + regmap_update_bits(es8326->regmap, ES8326_CLK_INV, 0xc0, 0x00); + regmap_update_bits(es8326->regmap, ES8326_CLK_MUX, 0x80, 0x00); if (direction == SNDRV_PCM_STREAM_PLAYBACK) { regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x01); usleep_range(1000, 5000); @@ -645,7 +647,7 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) } else { msleep(300); if (es8326->version > ES8326_VERSION_B) { - regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x50); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x70); regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x00); } regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE, @@ -676,6 +678,10 @@ static int es8326_set_bias_level(struct snd_soc_component *codec, regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00); regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x20); regmap_update_bits(es8326->regmap, ES8326_RESET, 0x02, 0x00); + if (es8326->version > ES8326_VERSION_B) { + regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x30); + } break; case SND_SOC_BIAS_PREPARE: break; @@ -683,6 +689,12 @@ static int es8326_set_bias_level(struct snd_soc_component *codec, regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b); regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x00); regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, ES8326_IO_INPUT); + if (es8326->version > ES8326_VERSION_B) { + regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x10); + } + regmap_update_bits(es8326->regmap, ES8326_CLK_INV, 0xc0, 0xc0); + regmap_update_bits(es8326->regmap, ES8326_CLK_MUX, 0x80, 0x80); break; case SND_SOC_BIAS_OFF: clk_disable_unprepare(es8326->mclk); @@ -773,7 +785,10 @@ static void es8326_jack_button_handler(struct work_struct *work) case 0x6f: case 0x4b: /* button volume up */ - cur_button = SND_JACK_BTN_1; + if ((iface == 0x6f) && (es8326->version > ES8326_VERSION_B)) + cur_button = SND_JACK_BTN_0; + else + cur_button = SND_JACK_BTN_1; break; case 0x27: /* button volume down */ @@ -1082,7 +1097,7 @@ static void es8326_init(struct snd_soc_component *component) regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66); es8326_disable_micbias(es8326->component); if (es8326->version > ES8326_VERSION_B) { - regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x13); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x10); regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); } diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c index 908846e994df..e17a142d03b9 100644 --- a/sound/soc/codecs/rt722-sdca.c +++ b/sound/soc/codecs/rt722-sdca.c @@ -1468,13 +1468,18 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722) 0x008d); /* check HP calibration FSM status */ for (loop_check = 0; loop_check < chk_cnt; loop_check++) { + usleep_range(10000, 11000); ret = rt722_sdca_index_read(rt722, RT722_VENDOR_CALI, RT722_DAC_DC_CALI_CTL3, &calib_status); - if (ret < 0 || loop_check == chk_cnt) + if (ret < 0) dev_dbg(&rt722->slave->dev, "calibration failed!, ret=%d\n", ret); if ((calib_status & 0x0040) == 0x0) break; } + + if (loop_check == chk_cnt) + dev_dbg(&rt722->slave->dev, "%s, calibration time-out!\n", __func__); + /* Set ADC09 power entity floating control */ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL, 0x2a12); diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index be2ca5eb6c93..728bf78ae71f 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -78,7 +78,7 @@ static const struct bulk_reg_val tas2781_cali_start_reg[] = { X2781_CL_STT_VAL(TAS2781_PRM_INT_MASK_REG, 0xfe, false), X2781_CL_STT_VAL(TAS2781_PRM_CLK_CFG_REG, 0xdd, false), X2781_CL_STT_VAL(TAS2781_PRM_RSVD_REG, 0x20, false), - X2781_CL_STT_VAL(TAS2781_PRM_TEST_57_REG, 0x14, false), + X2781_CL_STT_VAL(TAS2781_PRM_TEST_57_REG, 0x14, true), X2781_CL_STT_VAL(TAS2781_PRM_TEST_62_REG, 0x45, true), X2781_CL_STT_VAL(TAS2781_PRM_PVDD_UVLO_REG, 0x03, false), X2781_CL_STT_VAL(TAS2781_PRM_CHNL_0_REG, 0xa8, false), @@ -370,7 +370,7 @@ static void sngl_calib_start(struct tasdevice_priv *tas_priv, int i, tasdevice_dev_read(tas_priv, i, p[j].reg, (int *)&p[j].val[0]); } else { - switch (p[j].reg) { + switch (tas2781_cali_start_reg[j].reg) { case 0: { if (!reg[0]) continue; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 8e88830e8e57..678540b78280 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -29,8 +29,8 @@ config SND_SOC_FSL_SAI config SND_SOC_FSL_MQS tristate "Medium Quality Sound (MQS) module support" depends on SND_SOC_FSL_SAI + depends on IMX_SCMI_MISC_DRV || !IMX_SCMI_MISC_DRV select REGMAP_MMIO - select IMX_SCMI_MISC_DRV if IMX_SCMI_MISC_EXT !=n help Say Y if you want to add Medium Quality Sound (MQS) support for the Freescale CPUs. diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index b6ff04f7138a..ee946e0d3f49 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1204,7 +1204,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = { }, /* DPLL lock info get controller */ { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = RX_SAMPLE_RATE_KCONTROL, .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 1e0bfd59d511..9c184ab73468 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -171,7 +171,7 @@ static int fsl_xcvr_capds_put(struct snd_kcontrol *kcontrol, } static struct snd_kcontrol_new fsl_xcvr_earc_capds_kctl = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capabilities Data Structure", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = fsl_xcvr_type_capds_bytes_info, diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 5280c1b20d85..1f5c4e8ff1b9 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -771,7 +771,7 @@ static void graph_link_init(struct simple_util_priv *priv, of_node_get(port_codec); if (graph_lnk_is_multi(port_codec)) { ep_codec = graph_get_next_multi_ep(&port_codec); - of_node_put(port_cpu); + of_node_put(port_codec); port_codec = ep_to_port(ep_codec); } else { ep_codec = of_graph_get_next_port_endpoint(port_codec, NULL); diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index 93eba4fd2771..76078a7005b0 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -209,21 +209,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in return 0; } -static int avs_card_suspend_pre(struct snd_soc_card *card) -{ - struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, DA7219_DAI_NAME); - - return snd_soc_component_set_jack(codec_dai->component, NULL, NULL); -} - -static int avs_card_resume_post(struct snd_soc_card *card) -{ - struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, DA7219_DAI_NAME); - struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); - - return snd_soc_component_set_jack(codec_dai->component, jack, NULL); -} - static int avs_da7219_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; @@ -255,8 +240,6 @@ static int avs_da7219_probe(struct platform_device *pdev) card->name = "avs_da7219"; card->dev = dev; card->owner = THIS_MODULE; - card->suspend_pre = avs_card_suspend_pre; - card->resume_post = avs_card_resume_post; card->dai_link = dai_link; card->num_links = 1; card->controls = card_controls; diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 810be7c949a5..c9f9c9b0de9b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -632,7 +632,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .callback = sof_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "233C") + DMI_MATCH(DMI_PRODUCT_NAME, "21QB") }, /* Note this quirk excludes the CODEC mic */ .driver_data = (void *)(SOC_SDW_CODEC_MIC), @@ -641,9 +641,26 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .callback = sof_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "233B") + DMI_MATCH(DMI_PRODUCT_NAME, "21QA") }, - .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS), + /* Note this quirk excludes the CODEC mic */ + .driver_data = (void *)(SOC_SDW_CODEC_MIC), + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21Q6") + }, + .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC), + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21Q7") + }, + .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC), }, /* ArrowLake devices */ @@ -1067,8 +1084,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) return ret; } - /* One per DAI link, worst case is a DAI link for every endpoint */ - sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL); + /* + * One per DAI link, worst case is a DAI link for every endpoint, also + * add one additional to act as a terminator such that code can iterate + * until it hits an uninitialised DAI. + */ + sof_dais = kcalloc(num_ends + 1, sizeof(*sof_dais), GFP_KERNEL); if (!sof_dais) return -ENOMEM; diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c index 9b72b2a7ae91..6b6330583941 100644 --- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c +++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c @@ -120,8 +120,8 @@ int mtk_afe_pcm_new(struct snd_soc_component *component, struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); size = afe->mtk_afe_hardware->buffer_bytes_max; - snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, - afe->dev, size, size); + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, afe->dev, 0, size); + return 0; } EXPORT_SYMBOL_GPL(mtk_afe_pcm_new); diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c index e04b88a57535..2d0d04e0232d 100644 --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c @@ -188,9 +188,7 @@ SND_SOC_DAILINK_DEFS(pcm1, SND_SOC_DAILINK_DEFS(ul_src, DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC")), DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", - "mt6359-snd-codec-aif1"), - COMP_CODEC("dmic-codec", - "dmic-hifi")), + "mt6359-snd-codec-aif1")), DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(AFE_SOF_DL2, diff --git a/sound/soc/renesas/rcar/adg.c b/sound/soc/renesas/rcar/adg.c index 0f190abf00e7..191f212d338c 100644 --- a/sound/soc/renesas/rcar/adg.c +++ b/sound/soc/renesas/rcar/adg.c @@ -374,12 +374,12 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) return 0; } -void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) +int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct rsnd_mod *adg_mod = rsnd_mod_get(adg); struct clk *clk; - int i; + int ret = 0, i; if (enable) { rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr); @@ -389,18 +389,33 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) for_each_rsnd_clkin(clk, adg, i) { if (enable) { - clk_prepare_enable(clk); + ret = clk_prepare_enable(clk); /* * We shouldn't use clk_get_rate() under * atomic context. Let's keep it when * rsnd_adg_clk_enable() was called */ + if (ret < 0) + break; + adg->clkin_rate[i] = clk_get_rate(clk); } else { - clk_disable_unprepare(clk); + if (adg->clkin_rate[i]) + clk_disable_unprepare(clk); + + adg->clkin_rate[i] = 0; } } + + /* + * rsnd_adg_clk_enable() might return error (_disable() will not). + * We need to rollback in such case + */ + if (ret < 0) + rsnd_adg_clk_disable(priv); + + return ret; } static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv, @@ -753,7 +768,10 @@ int rsnd_adg_probe(struct rsnd_priv *priv) if (ret) return ret; - rsnd_adg_clk_enable(priv); + ret = rsnd_adg_clk_enable(priv); + if (ret) + return ret; + rsnd_adg_clk_dbg_info(priv, NULL); return 0; diff --git a/sound/soc/renesas/rcar/core.c b/sound/soc/renesas/rcar/core.c index e2234928c9e8..d3709fd0409e 100644 --- a/sound/soc/renesas/rcar/core.c +++ b/sound/soc/renesas/rcar/core.c @@ -2086,9 +2086,7 @@ static int __maybe_unused rsnd_resume(struct device *dev) { struct rsnd_priv *priv = dev_get_drvdata(dev); - rsnd_adg_clk_enable(priv); - - return 0; + return rsnd_adg_clk_enable(priv); } static const struct dev_pm_ops rsnd_pm_ops = { diff --git a/sound/soc/renesas/rcar/rsnd.h b/sound/soc/renesas/rcar/rsnd.h index 3c164d8e3b16..a5f54b65313c 100644 --- a/sound/soc/renesas/rcar/rsnd.h +++ b/sound/soc/renesas/rcar/rsnd.h @@ -608,7 +608,7 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod, struct rsnd_dai_stream *io); #define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1) #define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0) -void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable); +int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable); void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m); /* diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 4b1ea7b2c796..60b4b7b75215 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -127,8 +127,9 @@ config SND_SOC_SAMSUNG_TM2_WM5110 config SND_SOC_SAMSUNG_ARIES_WM8994 tristate "SoC I2S Audio support for WM8994 on Aries" - depends on SND_SOC_SAMSUNG && MFD_WM8994 && IIO && EXTCON + depends on SND_SOC_SAMSUNG && I2C && IIO && EXTCON select SND_SOC_BT_SCO + select MFD_WM8994 select SND_SOC_WM8994 select SND_SAMSUNG_I2S help @@ -140,8 +141,9 @@ config SND_SOC_SAMSUNG_ARIES_WM8994 config SND_SOC_SAMSUNG_MIDAS_WM1811 tristate "SoC I2S Audio support for Midas boards" - depends on SND_SOC_SAMSUNG && IIO + depends on SND_SOC_SAMSUNG && I2C && IIO select SND_SAMSUNG_I2S + select MFD_WM8994 select SND_SOC_WM8994 help Say Y if you want to add support for SoC audio on the Midas boards. diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c13f89b7065e..0db2a3e554fb 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -103,8 +103,10 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai return sdai->platform_private; } -int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream, - struct snd_soc_dai *cpu_dai) +static int +hda_link_dma_cleanup(struct snd_pcm_substream *substream, + struct hdac_ext_stream *hext_stream, + struct snd_soc_dai *cpu_dai, bool release) { const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct sof_intel_hda_stream *hda_stream; @@ -128,6 +130,17 @@ int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_st snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag); } + if (!release) { + /* + * Force stream reconfiguration without releasing the channel on + * subsequent stream restart (without free), including LinkDMA + * reset. + * The stream is released via hda_dai_hw_free() + */ + hext_stream->link_prepared = 0; + return 0; + } + if (ops->release_hext_stream) ops->release_hext_stream(sdev, cpu_dai, substream); @@ -211,7 +224,7 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, if (!hext_stream) return 0; - return hda_link_dma_cleanup(substream, hext_stream, cpu_dai); + return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, true); } static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream, @@ -304,7 +317,8 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i switch (cmd) { case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: - ret = hda_link_dma_cleanup(substream, hext_stream, dai); + ret = hda_link_dma_cleanup(substream, hext_stream, dai, + cmd == SNDRV_PCM_TRIGGER_STOP ? false : true); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); return ret; @@ -660,8 +674,7 @@ static int hda_dai_suspend(struct hdac_bus *bus) } ret = hda_link_dma_cleanup(hext_stream->link_substream, - hext_stream, - cpu_dai); + hext_stream, cpu_dai, true); if (ret < 0) return ret; } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 22bd9c3c8216..ee4ccc1a5490 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -1038,8 +1038,6 @@ const struct hda_dai_widget_dma_ops * hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, struct snd_sof_dai_config_data *data); -int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream, - struct snd_soc_dai *cpu_dai); static inline struct snd_sof_dev *widget_to_sdev(struct snd_soc_dapm_widget *w) { diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index c2fce554a674..e98b53b67d12 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -1588,14 +1588,14 @@ static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget) ret = sof_update_ipc_object(scomp, comp_dai, SOF_DAI_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*comp_dai), 1); if (ret < 0) - goto free; + goto free_comp; /* update comp_tokens */ ret = sof_update_ipc_object(scomp, &comp_dai->config, SOF_COMP_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(comp_dai->config), 1); if (ret < 0) - goto free; + goto free_comp; /* Subtract the base to match the FW dai index. */ if (comp_dai->type == SOF_DAI_INTEL_ALH) { @@ -1603,7 +1603,8 @@ static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget) dev_err(sdev->dev, "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n", comp_dai->dai_index, INTEL_ALH_DAI_INDEX_BASE); - return -EINVAL; + ret = -EINVAL; + goto free_comp; } comp_dai->dai_index -= INTEL_ALH_DAI_INDEX_BASE; } |