From 4c7518062d638837cea915e0ffe30f846780639a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Feb 2025 10:52:37 +0200 Subject: [PATCH 01/16] ASoC: SOF: ipc4: Add support for split firmware releases A split SOF release consists of a base firmware and two libraries: -openmodules.ri for processing (audio) modules -debug.ri for debug and developer modules To handle this new release model add infrastructure to try to load the two library after boot optionally. This approach will allow flexibility on handling platforms in sof-bin with single or split configuration: single release: base firmware only split release: base firmware + openmodules + debug The files for the split firmware are located at the firmware directory. Signed-off-by: Peter Ujfalusi Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20250206085237.19214-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-loader.c | 143 +++++++++++++++++++++++++++++------- sound/soc/sof/ipc4-priv.h | 1 + sound/soc/sof/ipc4.c | 8 +- 3 files changed, 126 insertions(+), 26 deletions(-) diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c index bcdb33d03682..6ad1ef0e53e8 100644 --- a/sound/soc/sof/ipc4-loader.c +++ b/sound/soc/sof/ipc4-loader.c @@ -169,21 +169,14 @@ static size_t sof_ipc4_fw_parse_basefw_ext_man(struct snd_sof_dev *sdev) return payload_offset; } -static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev, - unsigned long lib_id, const guid_t *uuid) +static int sof_ipc4_load_library(struct snd_sof_dev *sdev, unsigned long lib_id, + const char *lib_filename, bool optional) { struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct sof_ipc4_fw_library *fw_lib; - const char *fw_filename; ssize_t payload_offset; int ret, i, err; - if (!sdev->pdata->fw_lib_prefix) { - dev_err(sdev->dev, - "Library loading is not supported due to not set library path\n"); - return -EINVAL; - } - if (!ipc4_data->load_library) { dev_err(sdev->dev, "Library loading is not supported on this platform\n"); return -EOPNOTSUPP; @@ -193,21 +186,26 @@ static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev, if (!fw_lib) return -ENOMEM; - fw_filename = kasprintf(GFP_KERNEL, "%s/%pUL.bin", - sdev->pdata->fw_lib_prefix, uuid); - if (!fw_filename) { - ret = -ENOMEM; - goto free_fw_lib; - } - - ret = request_firmware(&fw_lib->sof_fw.fw, fw_filename, sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "Library file '%s' is missing\n", fw_filename); - goto free_filename; + if (optional) { + ret = firmware_request_nowarn(&fw_lib->sof_fw.fw, lib_filename, + sdev->dev); + if (ret < 0) { + /* optional library, override the error */ + ret = 0; + goto free_fw_lib; + } } else { - dev_dbg(sdev->dev, "Library file '%s' loaded\n", fw_filename); + ret = request_firmware(&fw_lib->sof_fw.fw, lib_filename, + sdev->dev); + if (ret < 0) { + dev_err(sdev->dev, "Library file '%s' is missing\n", + lib_filename); + goto free_fw_lib; + } } + dev_dbg(sdev->dev, "Library file '%s' loaded\n", lib_filename); + payload_offset = sof_ipc4_fw_parse_ext_man(sdev, fw_lib); if (payload_offset <= 0) { if (!payload_offset) @@ -251,22 +249,117 @@ static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev, if (unlikely(ret)) goto release; - kfree(fw_filename); - return 0; release: release_firmware(fw_lib->sof_fw.fw); /* Allocated within sof_ipc4_fw_parse_ext_man() */ devm_kfree(sdev->dev, fw_lib->modules); -free_filename: - kfree(fw_filename); free_fw_lib: devm_kfree(sdev->dev, fw_lib); return ret; } +/** + * sof_ipc4_complete_split_release - loads the library parts of a split firmware + * @sdev: SOF device + * + * With IPC4 the firmware can be a single binary or a split release. + * - single binary: only the basefw + * - split release: basefw and two libraries (openmodules, debug) + * + * With split firmware release it is also allowed that for example only the + * debug library is present (the openmodules content is built in the basefw). + * + * To handle the permutations try to load the openmodules then the debug + * libraries as optional ones after the basefw boot. + * + * The libraries for the split release are stored alongside the basefw on the + * filesystem. + */ +int sof_ipc4_complete_split_release(struct snd_sof_dev *sdev) +{ + static const char * const lib_bundle[] = { "openmodules", "debug" }; + const char *fw_filename = sdev->pdata->fw_filename; + const char *lib_filename, *p; + size_t lib_name_base_size; + unsigned long lib_id = 1; + char *lib_name_base; + int i; + + p = strstr(fw_filename, ".ri"); + if (!p || strlen(p) != 3) { + dev_info(sdev->dev, + "%s: Firmware name '%s' is missing .ri extension\n", + __func__, fw_filename); + return 0; + } + + /* Space for the firmware basename + '\0', without the extension */ + lib_name_base_size = strlen(fw_filename) - 2; + lib_name_base = kzalloc(lib_name_base_size, GFP_KERNEL); + if (!lib_name_base) + return -ENOMEM; + + /* + * strscpy will 0 terminate the copied string, removing the '.ri' from + * the end of the fw_filename, for example: + * fw_filename: "sof-ptl.ri\0" + * lib_name_base: "sof-ptl\0" + */ + strscpy(lib_name_base, fw_filename, lib_name_base_size); + + for (i = 0; i < ARRAY_SIZE(lib_bundle); i++) { + int ret; + + lib_filename = kasprintf(GFP_KERNEL, "%s/%s-%s.ri", + sdev->pdata->fw_filename_prefix, + lib_name_base, lib_bundle[i]); + if (!lib_filename) { + kfree(lib_name_base); + return -ENOMEM; + } + + ret = sof_ipc4_load_library(sdev, lib_id, lib_filename, true); + if (ret) + dev_warn(sdev->dev, "%s: Failed to load %s: %d\n", + __func__, lib_filename, ret); + else + lib_id++; + + kfree(lib_filename); + } + + kfree(lib_name_base); + + return 0; +} + +static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev, + unsigned long lib_id, const guid_t *uuid) +{ + const char *lib_filename; + int ret; + + if (!sdev->pdata->fw_lib_prefix) { + dev_err(sdev->dev, + "Library loading is not supported due to not set library path\n"); + return -EINVAL; + } + + lib_filename = kasprintf(GFP_KERNEL, "%s/%pUL.bin", + sdev->pdata->fw_lib_prefix, uuid); + if (!lib_filename) + return -ENOMEM; + + ret = sof_ipc4_load_library(sdev, lib_id, lib_filename, false); + + kfree(lib_filename); + + return ret; +} + struct sof_ipc4_fw_module *sof_ipc4_find_module_by_uuid(struct snd_sof_dev *sdev, const guid_t *uuid) { diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h index ea3323b90343..b798810eff91 100644 --- a/sound/soc/sof/ipc4-priv.h +++ b/sound/soc/sof/ipc4-priv.h @@ -101,6 +101,7 @@ extern const struct sof_ipc_fw_tracing_ops ipc4_mtrace_ops; int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 instance_id, u32 state); int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core); +int sof_ipc4_complete_split_release(struct snd_sof_dev *sdev); int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev); int sof_ipc4_reload_fw_libraries(struct snd_sof_dev *sdev); struct sof_ipc4_fw_module *sof_ipc4_find_module_by_uuid(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index 4386cbae16d4..2ed0c52fb2f1 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -825,8 +825,14 @@ static void sof_ipc4_exit(struct snd_sof_dev *sdev) static int sof_ipc4_post_boot(struct snd_sof_dev *sdev) { - if (sdev->first_boot) + if (sdev->first_boot) { + int ret = sof_ipc4_complete_split_release(sdev); + + if (ret) + return ret; + return sof_ipc4_query_fw_configuration(sdev); + } return sof_ipc4_reload_fw_libraries(sdev); } -- 2.51.0 From 943116ba2a6ab472e8ad2d1e57a3f10f13485cc2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:10 +0000 Subject: [PATCH 02/16] ASoC: add common snd_soc_ret() and use it Each soc-xxx.c is using own snd_xxx_ret(), but we want to share it. Let's add common snd_soc_ret() for it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frkt2qlx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-card.c | 14 ++------------ sound/soc/soc-component.c | 38 +++++++++++++------------------------- sound/soc/soc-dai.c | 18 ++---------------- sound/soc/soc-link.c | 18 ++---------------- sound/soc/soc-pcm.c | 18 ++---------------- sound/soc/soc-utils.c | 26 ++++++++++++++++++++++++++ 7 files changed, 48 insertions(+), 85 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index fcdb5adfcd5e..16e4e488521c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -539,6 +539,7 @@ int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots); int snd_soc_params_to_bclk(const struct snd_pcm_hw_params *parms); int snd_soc_tdm_params_to_bclk(const struct snd_pcm_hw_params *params, int tdm_width, int tdm_slots, int slot_multiple); +int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...); /* set runtime hw params */ static inline int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index e6eb71b3010a..235427d69061 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -15,18 +15,8 @@ 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; + return snd_soc_ret(card->dev, ret, + "at %s() on %s\n", func, card->name); } struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index b67ef78f405c..25f5e543ae8d 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -13,32 +13,20 @@ #include #include -#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret, -1) -#define soc_component_ret_reg_rw(dai, ret, reg) _soc_component_ret(dai, __func__, ret, reg) -static inline int _soc_component_ret(struct snd_soc_component *component, - const char *func, int ret, int reg) -{ - /* Positive/Zero values are not errors */ - if (ret >= 0) - return ret; - - /* Negative values might be errors */ - switch (ret) { - case -EPROBE_DEFER: - case -ENOTSUPP: - break; - default: - if (reg == -1) - dev_err(component->dev, - "ASoC: error at %s on %s: %d\n", - func, component->name, ret); - else - dev_err(component->dev, - "ASoC: error at %s on %s for register: [0x%08x] %d\n", - func, component->name, reg, ret); - } +#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret) +static inline int _soc_component_ret(struct snd_soc_component *component, const char *func, int ret) +{ + return snd_soc_ret(component->dev, ret, + "at %s() on %s\n", func, component->name); +} - return ret; +#define soc_component_ret_reg_rw(dai, ret, reg) _soc_component_ret_reg_rw(dai, __func__, ret, reg) +static inline int _soc_component_ret_reg_rw(struct snd_soc_component *component, + const char *func, int ret, int reg) +{ + return snd_soc_ret(component->dev, ret, + "at %s() on %s for register: [0x%08x]\n", + func, component->name, reg); } static inline int soc_component_field_shift(struct snd_soc_component *component, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index ca0308f6d41c..7c4c9127e5f3 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -14,22 +14,8 @@ static inline int _soc_dai_ret(const 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: - break; - default: - dev_err(dai->dev, - "ASoC: error at %s on %s: %d\n", - func, dai->name, ret); - } - - return ret; + return snd_soc_ret(dai->dev, ret, + "at %s() on %s\n", func, dai->name); } /* diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 7f1f1bc717e2..02fd68f2e702 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -12,22 +12,8 @@ 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: - break; - default: - dev_err(rtd->dev, - "ASoC: error at %s on %s: %d\n", - func, rtd->dai_link->name, ret); - } - - return ret; + return snd_soc_ret(rtd->dev, ret, + "at %s() on %s\n", func, rtd->dai_link->name); } /* diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 88b3ad5a2552..a2caa146cac2 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -30,22 +30,8 @@ static inline int _soc_pcm_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: - break; - default: - dev_err(rtd->dev, - "ASoC: error at %s on %s: %d\n", - func, rtd->dai_link->name, ret); - } - - return ret; + return snd_soc_ret(rtd->dev, ret, + "at %s() on %s\n", func, rtd->dai_link->name); } /* is the current PCM operation for this FE ? */ diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index aa93e77ac937..e8958158acc1 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -15,6 +15,32 @@ #include #include +int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + /* Positive, Zero values are not errors */ + if (ret >= 0) + return ret; + + /* Negative values might be errors */ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + break; + default: + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + + dev_err(dev, "ASoC error (%d): %pV", ret, &vaf); + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_ret); + int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots) { return sample_size * channels * tdm_slots; -- 2.51.0 From 062b7ef6b103dcbcb3c084e8ace8e74e260b2346 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:14 +0000 Subject: [PATCH 03/16] ASoC: soc-utils: care -EOPNOTSUPP on snd_soc_ret() We get below warning by checkpatch on soc-utils. Adds EOPNOTSUPP, but not remove existing ENOTSUPP. WARNING: ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ed0d2qlt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index e8958158acc1..318b141c00b3 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -28,6 +28,7 @@ int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...) switch (ret) { case -EPROBE_DEFER: case -ENOTSUPP: + case -EOPNOTSUPP: break; default: va_start(args, fmt); -- 2.51.0 From be61cd4242e4a53f5cf989ee7573121d041444bc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:19 +0000 Subject: [PATCH 04/16] ASoC: soc-pcm: use snd_soc_ret() Many functions uses below style for error return dev_err(dev, "message"); return -Exxxx; We can merge these into snd_soc_ret() which can use same error format. Let's cleaup code. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyfx2qlo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 96 ++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 57 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a2caa146cac2..ebe99d369ca9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -238,11 +238,9 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, int stream; char *buf; - if (fe->dai_link->num_cpus > 1) { - dev_err(fe->dev, + if (fe->dai_link->num_cpus > 1) + return snd_soc_ret(fe->dev, -EINVAL, "%s doesn't support Multi CPU yet\n", __func__); - return -EINVAL; - } buf = kmalloc(out_count, GFP_KERNEL); if (!buf) @@ -460,12 +458,9 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, ret = snd_pcm_hw_constraint_single(substream->runtime, \ SNDRV_PCM_HW_PARAM_##NAME,\ soc_dai->symmetric_##name); \ - if (ret < 0) { \ - dev_err(soc_dai->dev, \ - "ASoC: Unable to apply %s constraint: %d\n",\ - #name, ret); \ - return ret; \ - } \ + if (ret < 0) \ + return snd_soc_ret(soc_dai->dev, ret, \ + "Unable to apply %s constraint\n", #name); \ } __soc_pcm_apply_symmetry(rate, RATE); @@ -496,12 +491,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, for_each_rtd_cpu_dais(rtd, i, cpu_dai) \ if (!snd_soc_dai_is_dummy(cpu_dai) && \ cpu_dai->symmetric_##xxx && \ - cpu_dai->symmetric_##xxx != d.symmetric_##xxx) { \ - dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %s:%d - %s:%d\n", \ - #xxx, cpu_dai->name, cpu_dai->symmetric_##xxx, \ - d.name, d.symmetric_##xxx); \ - return -EINVAL; \ - } + cpu_dai->symmetric_##xxx != d.symmetric_##xxx) \ + return snd_soc_ret(rtd->dev, -EINVAL, \ + "unmatched %s symmetry: %s:%d - %s:%d\n", \ + #xxx, cpu_dai->name, cpu_dai->symmetric_##xxx, \ + d.name, d.symmetric_##xxx); /* reject unmatched parameters when applying symmetry */ __soc_pcm_params_symmetry(rate); @@ -846,9 +840,8 @@ static int soc_hw_sanity_check(struct snd_pcm_substream *substream) return 0; config_err: - dev_err(dev, "ASoC: %s <-> %s No matching %s\n", - name_codec, name_cpu, err_msg); - return -EINVAL; + return snd_soc_ret(dev, -EINVAL, + "%s <-> %s No matching %s\n", name_codec, name_cpu, err_msg); } /* @@ -1319,11 +1312,11 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, fe_substream = snd_soc_dpcm_get_substream(fe, stream); be_substream = snd_soc_dpcm_get_substream(be, stream); - if (!fe_substream->pcm->nonatomic && be_substream->pcm->nonatomic) { - dev_err(be->dev, "%s: FE is atomic but BE is nonatomic, invalid configuration\n", - __func__); - return -EINVAL; - } + if (!fe_substream->pcm->nonatomic && be_substream->pcm->nonatomic) + return snd_soc_ret(be->dev, -EINVAL, + "%s: %s is atomic but %s is nonatomic, invalid configuration\n", + __func__, fe->dai_link->name, be->dai_link->name); + if (fe_substream->pcm->nonatomic && !be_substream->pcm->nonatomic) { dev_dbg(be->dev, "FE is nonatomic but BE is not, forcing BE as nonatomic\n"); be_substream->pcm->nonatomic = 1; @@ -1493,11 +1486,9 @@ int dpcm_path_get(struct snd_soc_pcm_runtime *fe, struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0); int paths; - if (fe->dai_link->num_cpus > 1) { - dev_err(fe->dev, + if (fe->dai_link->num_cpus > 1) + return snd_soc_ret(fe->dev, -EINVAL, "%s doesn't support Multi CPU yet\n", __func__); - return -EINVAL; - } /* get number of valid DAI paths and their widgets */ paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list, @@ -2388,23 +2379,23 @@ static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, ret = soc_pcm_trigger(substream, cmd); if (ret < 0) - return ret; + goto end; ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); - return ret; + goto end; } /* call trigger on the frontend after the backend. */ ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); if (ret < 0) - return ret; + goto end; dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", fe->dai_link->name, cmd); ret = soc_pcm_trigger(substream, cmd); - - return ret; +end: + return snd_soc_ret(fe->dev, ret, "trigger FE cmd: %d failed\n", cmd); } static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) @@ -2460,11 +2451,8 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) goto out; } - if (ret < 0) { - dev_err(fe->dev, "ASoC: trigger FE cmd: %d failed: %d\n", - cmd, ret); + if (ret < 0) goto out; - } switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -2693,11 +2681,9 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) if (!fe->dai_link->dynamic) return 0; - if (fe->dai_link->num_cpus > 1) { - dev_err(fe->dev, + if (fe->dai_link->num_cpus > 1) + return snd_soc_ret(fe->dev, -EINVAL, "%s doesn't support Multi CPU yet\n", __func__); - return -EINVAL; - } /* only check active links */ if (!snd_soc_dai_active(snd_soc_rtd_to_cpu(fe, 0))) @@ -2768,7 +2754,8 @@ int snd_soc_dpcm_runtime_update(struct snd_soc_card *card) out: snd_soc_dpcm_mutex_unlock(card); - return ret; + + return snd_soc_ret(card->dev, ret, "%s() failed\n", __func__); } EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update); @@ -2842,10 +2829,9 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, int has_capture = 0; int i; - if (dai_link->dynamic && dai_link->num_cpus > 1) { - dev_err(rtd->dev, "DPCM doesn't support Multi CPU for Front-Ends yet\n"); - return -EINVAL; - } + if (dai_link->dynamic && dai_link->num_cpus > 1) + return snd_soc_ret(rtd->dev, -EINVAL, + "DPCM doesn't support Multi CPU for Front-Ends yet\n"); /* Adapt stream for codec2codec links */ cpu_capture = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_CAPTURE); @@ -2887,12 +2873,9 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, if (dai_link->capture_only) has_playback = 0; - if (!has_playback && !has_capture) { - dev_err(rtd->dev, "substream %s has no playback, no capture\n", - dai_link->stream_name); - - return -EINVAL; - } + if (!has_playback && !has_capture) + return snd_soc_ret(rtd->dev, -EINVAL, + "substream %s has no playback, no capture\n", dai_link->stream_name); *playback = has_playback; *capture = has_capture; @@ -2932,11 +2915,10 @@ static int soc_create_pcm(struct snd_pcm **pcm, ret = snd_pcm_new(rtd->card->snd_card, new_name, rtd->id, playback, capture, pcm); } - if (ret < 0) { - dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n", - new_name, rtd->dai_link->name, ret); - return ret; - } + if (ret < 0) + return snd_soc_ret(rtd->dev, ret, + "can't create pcm %s for dailink %s\n", new_name, rtd->dai_link->name); + dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n", rtd->id, new_name); return 0; -- 2.51.0 From a0ef5b4b101424b8a666ed56bf1717dafe2d37f5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:23 +0000 Subject: [PATCH 05/16] ASoC: simple-card: use snd_soc_ret() We can use snd_soc_ret() to indicate error message when return. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjvh2qlk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 130 +++++++++++++++++--------------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index afe7e79ffdbd..004fda4504c4 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -29,7 +29,16 @@ static const struct snd_soc_ops simple_ops = { .hw_params = simple_util_hw_params, }; -static int simple_parse_platform(struct device_node *node, struct snd_soc_dai_link_component *dlc) +#define simple_ret(priv, ret) _simple_ret(priv, __func__, ret) +static inline int _simple_ret(struct simple_util_priv *priv, + const char *func, int ret) +{ + return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); +} + +static int simple_parse_platform(struct simple_util_priv *priv, + struct device_node *node, + struct snd_soc_dai_link_component *dlc) { struct of_phandle_args args; int ret; @@ -43,7 +52,7 @@ static int simple_parse_platform(struct device_node *node, struct snd_soc_dai_li */ ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); if (ret) - return ret; + return simple_ret(priv, ret); /* dai_name is not required and may not exist for plat component */ @@ -52,11 +61,12 @@ static int simple_parse_platform(struct device_node *node, struct snd_soc_dai_li return 0; } -static int simple_parse_dai(struct device *dev, +static int simple_parse_dai(struct simple_util_priv *priv, struct device_node *node, struct snd_soc_dai_link_component *dlc, int *is_single_link) { + struct device *dev = simple_priv_to_dev(priv); struct of_phandle_args args; struct snd_soc_dai *dai; int ret; @@ -70,17 +80,18 @@ static int simple_parse_dai(struct device *dev, */ ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); if (ret) - return ret; + goto end; /* * Try to find from DAI args */ dai = snd_soc_get_dai_via_args(&args); if (dai) { + ret = -ENOMEM; dlc->dai_name = snd_soc_dai_name_get(dai); dlc->dai_args = snd_soc_copy_dai_args(dev, &args); if (!dlc->dai_args) - return -ENOMEM; + goto end; goto parse_dai_end; } @@ -106,13 +117,14 @@ static int simple_parse_dai(struct device *dev, */ ret = snd_soc_get_dlc(&args, dlc); if (ret < 0) - return ret; + goto end; parse_dai_end: if (is_single_link) *is_single_link = !args.args_count; - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } static void simple_parse_convert(struct device *dev, @@ -149,19 +161,17 @@ static int simple_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, 0); } - ret = simple_parse_dai(dev, np, dlc, cpu); + ret = simple_parse_dai(priv, np, dlc, cpu); if (ret) - return ret; + goto end; ret = simple_util_parse_clk(dev, np, dai, dlc); if (ret) - return ret; + goto end; ret = simple_util_parse_tdm(np, dai); - if (ret) - return ret; - - return 0; +end: + return simple_ret(priv, ret); } static int simple_link_init(struct simple_util_priv *priv, @@ -183,7 +193,7 @@ static int simple_link_init(struct simple_util_priv *priv, ret = simple_util_parse_daifmt(dev, node, codec, prefix, &dai_link->dai_fmt); if (ret < 0) - return ret; + goto end; graph_util_parse_link_direction(top, &playback_only, &capture_only); graph_util_parse_link_direction(node, &playback_only, &capture_only); @@ -213,7 +223,9 @@ static int simple_link_init(struct simple_util_priv *priv, dai_link->init = simple_util_dai_init; dai_link->ops = &simple_ops; - return simple_util_set_dailink_name(dev, dai_link, name); + ret = simple_util_set_dailink_name(dev, dai_link, name); +end: + return simple_ret(priv, ret); } static int simple_dai_link_of_dpcm(struct simple_util_priv *priv, @@ -290,7 +302,7 @@ static int simple_dai_link_of_dpcm(struct simple_util_priv *priv, out_put_node: li->link++; - return ret; + return simple_ret(priv, ret); } static int simple_dai_link_of(struct simple_util_priv *priv, @@ -330,7 +342,7 @@ static int simple_dai_link_of(struct simple_util_priv *priv, if (ret < 0) goto dai_link_of_err; - ret = simple_parse_platform(plat, platforms); + ret = simple_parse_platform(priv, plat, platforms); if (ret < 0) goto dai_link_of_err; @@ -345,7 +357,7 @@ static int simple_dai_link_of(struct simple_util_priv *priv, dai_link_of_err: li->link++; - return ret; + return simple_ret(priv, ret); } static int __simple_for_each_link(struct simple_util_priv *priv, @@ -443,10 +455,10 @@ static int __simple_for_each_link(struct simple_util_priv *priv, node = of_get_next_child(top, node); } while (!is_top && node); - error: +error: of_node_put(node); - return ret; + return simple_ret(priv, ret); } static int simple_for_each_link(struct simple_util_priv *priv, @@ -479,7 +491,7 @@ static int simple_for_each_link(struct simple_util_priv *priv, break; } - return ret; + return simple_ret(priv, ret); } static void simple_depopulate_aux(void *data) @@ -500,9 +512,11 @@ static int simple_populate_aux(struct simple_util_priv *priv) ret = of_platform_populate(node, NULL, NULL, dev); if (ret) - return ret; + goto end; - return devm_add_action_or_reset(dev, simple_depopulate_aux, priv); + ret = devm_add_action_or_reset(dev, simple_depopulate_aux, priv); +end: + return simple_ret(priv, ret); } static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li) @@ -512,15 +526,15 @@ static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li) ret = simple_util_parse_widgets(card, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_routing(card, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_pin_switches(card, PREFIX); if (ret < 0) - return ret; + goto end; /* Single/Muti DAI link(s) & New style of DT node */ memset(li, 0, sizeof(*li)); @@ -528,19 +542,19 @@ static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li) simple_dai_link_of, simple_dai_link_of_dpcm); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_card_name(card, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_populate_aux(priv); if (ret < 0) - return ret; + goto end; ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs"); - - return ret; +end: + return simple_ret(priv, ret); } static int simple_count_noml(struct simple_util_priv *priv, @@ -548,12 +562,10 @@ static int simple_count_noml(struct simple_util_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - if (li->link >= SNDRV_MAX_LINKS) { - struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; - dev_err(dev, "too many links\n"); - return -EINVAL; - } + if (li->link >= SNDRV_MAX_LINKS) + goto end; /* * DON'T REMOVE platforms @@ -575,8 +587,9 @@ static int simple_count_noml(struct simple_util_priv *priv, li->num[li->link].codecs = 1; li->link += 1; - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } static int simple_count_dpcm(struct simple_util_priv *priv, @@ -584,12 +597,10 @@ static int simple_count_dpcm(struct simple_util_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - if (li->link >= SNDRV_MAX_LINKS) { - struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; - dev_err(dev, "too many links\n"); - return -EINVAL; - } + if (li->link >= SNDRV_MAX_LINKS) + goto end; if (li->cpu) { /* @@ -606,8 +617,9 @@ static int simple_count_dpcm(struct simple_util_priv *priv, li->link++; /* dummy-Codec */ } - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } static int simple_get_dais_count(struct simple_util_priv *priv, @@ -683,17 +695,15 @@ static int simple_soc_probe(struct snd_soc_card *card) ret = simple_util_init_hp(card, &priv->hp_jack, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_util_init_mic(card, &priv->mic_jack, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_util_init_aux_jacks(priv, PREFIX); - if (ret < 0) - return ret; - - return 0; +end: + return simple_ret(priv, ret); } static int simple_probe(struct platform_device *pdev) @@ -715,20 +725,22 @@ static int simple_probe(struct platform_device *pdev) card->probe = simple_soc_probe; card->driver_name = "simple-card"; + ret = -ENOMEM; struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL); if (!li) - return -ENOMEM; + goto end; ret = simple_get_dais_count(priv, li); if (ret < 0) - return ret; + goto end; + ret = -EINVAL; if (!li->link) - return -EINVAL; + goto end; ret = simple_util_init_priv(priv, li); if (ret < 0) - return ret; + goto end; if (np && of_device_is_available(np)) { @@ -795,8 +807,8 @@ static int simple_probe(struct platform_device *pdev) return 0; err: simple_util_clean_reference(card); - - return ret; +end: + return dev_err_probe(dev, ret, "parse error\n"); } static const struct of_device_id simple_of_match[] = { -- 2.51.0 From 2d7395b23dbf4c2d60be49b73e4c4705fc446662 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:27 +0000 Subject: [PATCH 06/16] ASoC: simple-card-utils: use snd_soc_ret() We can use snd_soc_ret() to indicate error message when return. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5b12qlg.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 8 +- sound/soc/generic/audio-graph-card.c | 6 +- sound/soc/generic/audio-graph-card2.c | 14 +-- sound/soc/generic/simple-card-utils.c | 170 +++++++++++++++----------- sound/soc/generic/simple-card.c | 4 +- 5 files changed, 115 insertions(+), 87 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 892f70532363..69a9c9c4d0e9 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -142,14 +142,14 @@ int simple_util_parse_daifmt(struct device *dev, struct device_node *codec, char *prefix, unsigned int *retfmt); -int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np, +int simple_util_parse_tdm_width_map(struct simple_util_priv *priv, struct device_node *np, struct simple_util_dai *dai); __printf(3, 4) -int simple_util_set_dailink_name(struct device *dev, +int simple_util_set_dailink_name(struct simple_util_priv *priv, struct snd_soc_dai_link *dai_link, const char *fmt, ...); -int simple_util_parse_card_name(struct snd_soc_card *card, +int simple_util_parse_card_name(struct simple_util_priv *priv, char *prefix); int simple_util_parse_clk(struct device *dev, @@ -201,7 +201,7 @@ void simple_util_remove(struct platform_device *pdev); int graph_util_card_probe(struct snd_soc_card *card); int graph_util_is_ports0(struct device_node *port); -int graph_util_parse_dai(struct device *dev, struct device_node *ep, +int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep, struct snd_soc_dai_link_component *dlc, int *is_single_link); void graph_util_parse_link_direction(struct device_node *np, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 7c422535b01a..bd7ebbec0fc9 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -111,7 +111,7 @@ static int graph_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, 0); } - ret = graph_util_parse_dai(dev, ep, dlc, cpu); + ret = graph_util_parse_dai(priv, ep, dlc, cpu); if (ret < 0) return ret; @@ -183,7 +183,7 @@ static int graph_link_init(struct simple_util_priv *priv, if (priv->ops) dai_link->ops = priv->ops; - return simple_util_set_dailink_name(dev, dai_link, name); + return simple_util_set_dailink_name(priv, dai_link, name); } static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, @@ -586,7 +586,7 @@ int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev) if (ret < 0) goto err; - ret = simple_util_parse_card_name(card, NULL); + ret = simple_util_parse_card_name(priv, NULL); if (ret < 0) goto err; diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index ee94b256b770..945a16e6d691 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -409,7 +409,7 @@ static int __graph_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, idx); } - ret = graph_util_parse_dai(dev, ep, dlc, &is_single_links); + ret = graph_util_parse_dai(priv, ep, dlc, &is_single_links); if (ret < 0) return ret; @@ -417,7 +417,7 @@ static int __graph_parse_node(struct simple_util_priv *priv, if (ret < 0) return ret; - ret = simple_util_parse_tdm_width_map(dev, ep, dai); + ret = simple_util_parse_tdm_width_map(priv, ep, dai); if (ret < 0) return ret; @@ -443,22 +443,22 @@ static int __graph_parse_node(struct simple_util_priv *priv, case GRAPH_NORMAL: /* run is_cpu only. see audio_graph2_link_normal() */ if (is_cpu) - simple_util_set_dailink_name(dev, dai_link, "%s%s-%s%s", + simple_util_set_dailink_name(priv, dai_link, "%s%s-%s%s", cpus->dai_name, cpu_multi, codecs->dai_name, codec_multi); break; case GRAPH_DPCM: if (is_cpu) - simple_util_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s", + simple_util_set_dailink_name(priv, dai_link, "fe.%pOFP.%s%s", cpus->of_node, cpus->dai_name, cpu_multi); else - simple_util_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s", + simple_util_set_dailink_name(priv, dai_link, "be.%pOFP.%s%s", codecs->of_node, codecs->dai_name, codec_multi); break; case GRAPH_C2C: /* run is_cpu only. see audio_graph2_link_c2c() */ if (is_cpu) - simple_util_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s", + simple_util_set_dailink_name(priv, dai_link, "c2c.%s%s-%s%s", cpus->dai_name, cpu_multi, codecs->dai_name, codec_multi); break; @@ -1332,7 +1332,7 @@ int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev, if (ret < 0) goto err; - ret = simple_util_parse_card_name(card, NULL); + ret = simple_util_parse_card_name(priv, NULL); if (ret < 0) goto err; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index c2445c5ccd84..51e0e434514d 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -15,6 +15,13 @@ #include #include +#define simple_ret(priv, ret) _simple_ret(priv, __func__, ret) +static inline int _simple_ret(struct simple_util_priv *priv, + const char *func, int ret) +{ + return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); +} + int simple_util_get_sample_fmt(struct simple_util_data *data) { int i; @@ -133,33 +140,42 @@ int simple_util_parse_daifmt(struct device *dev, } EXPORT_SYMBOL_GPL(simple_util_parse_daifmt); -int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np, +int simple_util_parse_tdm_width_map(struct simple_util_priv *priv, struct device_node *np, struct simple_util_dai *dai) { + struct device *dev = simple_priv_to_dev(priv); int n, i, ret; u32 *p; + /* + * NOTE + * + * Clang doesn't allow to use "goto end" before calling __free(), + * because it bypasses the initialization. Use simple_ret() directly. + */ + n = of_property_count_elems_of_size(np, "dai-tdm-slot-width-map", sizeof(u32)); if (n <= 0) return 0; + if (n % 3) { dev_err(dev, "Invalid number of cells for dai-tdm-slot-width-map\n"); - return -EINVAL; + return simple_ret(priv, -EINVAL); /* see NOTE */ } + ret = -ENOMEM; dai->tdm_width_map = devm_kcalloc(dev, n, sizeof(*dai->tdm_width_map), GFP_KERNEL); if (!dai->tdm_width_map) - return -ENOMEM; + return simple_ret(priv, ret); /* see NOTE */ - u32 *array_values __free(kfree) = kcalloc(n, sizeof(*array_values), - GFP_KERNEL); + u32 *array_values __free(kfree) = kcalloc(n, sizeof(*array_values), GFP_KERNEL); if (!array_values) - return -ENOMEM; + goto end; ret = of_property_read_u32_array(np, "dai-tdm-slot-width-map", array_values, n); if (ret < 0) { dev_err(dev, "Could not read dai-tdm-slot-width-map: %d\n", ret); - return ret; + goto end; } p = array_values; @@ -170,15 +186,17 @@ int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np, } dai->n_tdm_widths = i; - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_parse_tdm_width_map); -int simple_util_set_dailink_name(struct device *dev, +int simple_util_set_dailink_name(struct simple_util_priv *priv, struct snd_soc_dai_link *dai_link, const char *fmt, ...) { + struct device *dev = simple_priv_to_dev(priv); va_list ap; char *name = NULL; int ret = -ENOMEM; @@ -194,13 +212,14 @@ int simple_util_set_dailink_name(struct device *dev, dai_link->stream_name = name; } - return ret; + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_set_dailink_name); -int simple_util_parse_card_name(struct snd_soc_card *card, +int simple_util_parse_card_name(struct simple_util_priv *priv, char *prefix) { + struct snd_soc_card *card = simple_priv_to_card(priv); int ret; if (!prefix) @@ -214,13 +233,13 @@ int simple_util_parse_card_name(struct snd_soc_card *card, snprintf(prop, sizeof(prop), "%sname", prefix); ret = snd_soc_of_parse_card_name(card, prop); if (ret < 0) - return ret; + goto end; } if (!card->name && card->dai_link) card->name = card->dai_link->name; - - return 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_parse_card_name); @@ -348,7 +367,8 @@ cpu_err: break; simple_clk_disable(dai); } - return ret; + + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_startup); @@ -379,16 +399,19 @@ void simple_util_shutdown(struct snd_pcm_substream *substream) } EXPORT_SYMBOL_GPL(simple_util_shutdown); -static int simple_set_clk_rate(struct device *dev, - struct simple_util_dai *simple_dai, - unsigned long rate) +static int simple_set_clk_rate(struct simple_util_priv *priv, + struct simple_util_dai *simple_dai, + unsigned long rate) { + struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; + if (!simple_dai) return 0; if (simple_dai->clk_fixed && rate != simple_dai->sysclk) { dev_err(dev, "dai %s invalid clock rate %lu\n", simple_dai->name, rate); - return -EINVAL; + goto end; } if (!simple_dai->clk) @@ -397,12 +420,15 @@ static int simple_set_clk_rate(struct device *dev, if (clk_get_rate(simple_dai->clk) == rate) return 0; - return clk_set_rate(simple_dai->clk, rate); + ret = clk_set_rate(simple_dai->clk, rate); +end: + return simple_ret(priv, ret); } -static int simple_set_tdm(struct snd_soc_dai *dai, - struct simple_util_dai *simple_dai, - struct snd_pcm_hw_params *params) +static int simple_set_tdm(struct simple_util_priv *priv, + struct snd_soc_dai *dai, + struct simple_util_dai *simple_dai, + struct snd_pcm_hw_params *params) { int sample_bits = params_width(params); int slot_width, slot_count; @@ -430,12 +456,8 @@ static int simple_set_tdm(struct snd_soc_dai *dai, simple_dai->rx_slot_mask, slot_count, slot_width); - if (ret && ret != -ENOTSUPP) { - dev_err(dai->dev, "simple-card: set_tdm_slot error: %d\n", ret); - return ret; - } - return 0; + return simple_ret(priv, ret); } int simple_util_hw_params(struct snd_pcm_substream *substream, @@ -457,15 +479,15 @@ int simple_util_hw_params(struct snd_pcm_substream *substream, mclk = params_rate(params) * mclk_fs; for_each_prop_dai_codec(props, i, pdai) { - ret = simple_set_clk_rate(rtd->dev, pdai, mclk); + ret = simple_set_clk_rate(priv, pdai, mclk); if (ret < 0) - return ret; + goto end; } for_each_prop_dai_cpu(props, i, pdai) { - ret = simple_set_clk_rate(rtd->dev, pdai, mclk); + ret = simple_set_clk_rate(priv, pdai, mclk); if (ret < 0) - return ret; + goto end; } /* Ensure sysclk is set on all components in case any @@ -476,39 +498,40 @@ int simple_util_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_component_set_sysclk(component, 0, 0, mclk, SND_SOC_CLOCK_IN); if (ret && ret != -ENOTSUPP) - return ret; + goto end; } for_each_rtd_codec_dais(rtd, i, sdai) { pdai = simple_props_to_dai_codec(props, i); ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, pdai->clk_direction); if (ret && ret != -ENOTSUPP) - return ret; + goto end; } for_each_rtd_cpu_dais(rtd, i, sdai) { pdai = simple_props_to_dai_cpu(props, i); ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, pdai->clk_direction); if (ret && ret != -ENOTSUPP) - return ret; + goto end; } } for_each_prop_dai_codec(props, i, pdai) { sdai = snd_soc_rtd_to_codec(rtd, i); - ret = simple_set_tdm(sdai, pdai, params); + ret = simple_set_tdm(priv, sdai, pdai, params); if (ret < 0) - return ret; + goto end; } for_each_prop_dai_cpu(props, i, pdai) { sdai = snd_soc_rtd_to_cpu(rtd, i); - ret = simple_set_tdm(sdai, pdai, params); + ret = simple_set_tdm(priv, sdai, pdai, params); if (ret < 0) - return ret; + goto end; } - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_hw_params); @@ -536,7 +559,8 @@ int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, } EXPORT_SYMBOL_GPL(simple_util_be_hw_params_fixup); -static int simple_init_dai(struct snd_soc_dai *dai, struct simple_util_dai *simple_dai) +static int simple_init_dai(struct simple_util_priv *priv, + struct snd_soc_dai *dai, struct simple_util_dai *simple_dai) { int ret; @@ -548,7 +572,7 @@ static int simple_init_dai(struct snd_soc_dai *dai, struct simple_util_dai *simp simple_dai->clk_direction); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_sysclk error\n"); - return ret; + goto end; } } @@ -560,11 +584,12 @@ static int simple_init_dai(struct snd_soc_dai *dai, struct simple_util_dai *simp simple_dai->slot_width); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); - return ret; + goto end; } } - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } static inline int simple_component_is_codec(struct snd_soc_component *component) @@ -572,7 +597,8 @@ static inline int simple_component_is_codec(struct snd_soc_component *component) return component->driver->endianness; } -static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, +static int simple_init_for_codec2codec(struct simple_util_priv *priv, + struct snd_soc_pcm_runtime *rtd, struct simple_dai_props *dai_props) { struct snd_soc_dai_link *dai_link = rtd->dai_link; @@ -604,12 +630,13 @@ static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, if (ret < 0) { dev_err(rtd->dev, "simple-card: no valid dai_link params\n"); - return ret; + goto end; } + ret = -ENOMEM; c2c_params = devm_kzalloc(rtd->dev, sizeof(*c2c_params), GFP_KERNEL); if (!c2c_params) - return -ENOMEM; + goto end; c2c_params->formats = hw.formats; c2c_params->rates = hw.rates; @@ -621,7 +648,9 @@ static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, dai_link->c2c_params = c2c_params; dai_link->num_c2c_params = 1; - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd) @@ -632,21 +661,19 @@ int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd) int i, ret; for_each_prop_dai_codec(props, i, dai) { - ret = simple_init_dai(snd_soc_rtd_to_codec(rtd, i), dai); + ret = simple_init_dai(priv, snd_soc_rtd_to_codec(rtd, i), dai); if (ret < 0) - return ret; + goto end; } for_each_prop_dai_cpu(props, i, dai) { - ret = simple_init_dai(snd_soc_rtd_to_cpu(rtd, i), dai); + ret = simple_init_dai(priv, snd_soc_rtd_to_cpu(rtd, i), dai); if (ret < 0) - return ret; + goto end; } - ret = simple_init_for_codec2codec(rtd, props); - if (ret < 0) - return ret; - - return 0; + ret = simple_init_for_codec2codec(priv, rtd, props); +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_dai_init); @@ -831,7 +858,7 @@ int simple_util_init_aux_jacks(struct simple_util_priv *priv, char *prefix) priv->aux_jacks = devm_kcalloc(card->dev, num, sizeof(struct snd_soc_jack), GFP_KERNEL); if (!priv->aux_jacks) - return -ENOMEM; + return simple_ret(priv, -ENOMEM); for_each_card_auxs(card, component) { char id[128]; @@ -992,13 +1019,11 @@ int graph_util_card_probe(struct snd_soc_card *card) ret = simple_util_init_hp(card, &priv->hp_jack, NULL); if (ret < 0) - return ret; + goto end; ret = simple_util_init_mic(card, &priv->mic_jack, NULL); - if (ret < 0) - return ret; - - return 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(graph_util_card_probe); @@ -1074,9 +1099,10 @@ static int graph_get_dai_id(struct device_node *ep) return id; } -int graph_util_parse_dai(struct device *dev, struct device_node *ep, +int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep, struct snd_soc_dai_link_component *dlc, int *is_single_link) { + struct device *dev = simple_priv_to_dev(priv); struct of_phandle_args args = {}; struct snd_soc_dai *dai; int ret; @@ -1092,11 +1118,12 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, args.np = ep; dai = snd_soc_get_dai_via_args(&args); if (dai) { + ret = -ENOMEM; dlc->of_node = node; dlc->dai_name = snd_soc_dai_name_get(dai); dlc->dai_args = snd_soc_copy_dai_args(dev, &args); if (!dlc->dai_args) - return -ENOMEM; + goto end; goto parse_dai_end; } @@ -1127,13 +1154,14 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, */ ret = snd_soc_get_dlc(&args, dlc); if (ret < 0) - return ret; + goto end; parse_dai_end: if (is_single_link) *is_single_link = of_graph_get_endpoint_count(node) == 1; - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(graph_util_parse_dai); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 004fda4504c4..5af6d1b308f2 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -223,7 +223,7 @@ static int simple_link_init(struct simple_util_priv *priv, dai_link->init = simple_util_dai_init; dai_link->ops = &simple_ops; - ret = simple_util_set_dailink_name(dev, dai_link, name); + ret = simple_util_set_dailink_name(priv, dai_link, name); end: return simple_ret(priv, ret); } @@ -544,7 +544,7 @@ static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li) if (ret < 0) goto end; - ret = simple_util_parse_card_name(card, PREFIX); + ret = simple_util_parse_card_name(priv, PREFIX); if (ret < 0) goto end; -- 2.51.0 From 74a0ca4c7f19f1b273d665b3b53f7ae8af879658 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:31 +0000 Subject: [PATCH 07/16] ASoC: audio-graph-card: use snd_soc_ret() We can use snd_soc_ret() to indicate error message when return. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qql2qlc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 93 +++++++++++++++------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index bd7ebbec0fc9..a8a3bad3df00 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -20,6 +20,13 @@ #define DPCM_SELECTABLE 1 +#define graph_ret(priv, ret) _graph_ret(priv, __func__, ret) +static inline int _graph_ret(struct simple_util_priv *priv, + const char *func, int ret) +{ + return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); +} + #define ep_to_port(ep) of_get_parent(ep) static struct device_node *port_to_ports(struct device_node *port) { @@ -113,17 +120,15 @@ static int graph_parse_node(struct simple_util_priv *priv, ret = graph_util_parse_dai(priv, ep, dlc, cpu); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_tdm(ep, dai); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_clk(dev, ep, dai, dlc); - if (ret < 0) - return ret; - - return 0; +end: + return graph_ret(priv, ret); } static int graph_link_init(struct simple_util_priv *priv, @@ -148,7 +153,7 @@ static int graph_link_init(struct simple_util_priv *priv, ret = simple_util_parse_daifmt(dev, ep_cpu, ep_codec, NULL, &dai_link->dai_fmt); if (ret < 0) - return ret; + goto end; graph_util_parse_link_direction(top, &playback_only, &capture_only); graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only); @@ -183,7 +188,9 @@ static int graph_link_init(struct simple_util_priv *priv, if (priv->ops) dai_link->ops = priv->ops; - return simple_util_set_dailink_name(priv, dai_link, name); + ret = simple_util_set_dailink_name(priv, dai_link, name); +end: + return graph_ret(priv, ret); } static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, @@ -215,7 +222,7 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, ret = graph_parse_node(priv, cpu_ep, li, &is_single_links); if (ret) - return ret; + goto end; snprintf(dai_name, sizeof(dai_name), "fe.%pOFP.%s", cpus->of_node, cpus->dai_name); @@ -248,7 +255,7 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, ret = graph_parse_node(priv, codec_ep, li, NULL); if (ret < 0) - return ret; + goto end; snprintf(dai_name, sizeof(dai_name), "be.%pOFP.%s", codecs->of_node, codecs->dai_name); @@ -267,8 +274,8 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name); li->link++; - - return ret; +end: + return graph_ret(priv, ret); } static int graph_dai_link_of(struct simple_util_priv *priv, @@ -288,11 +295,11 @@ static int graph_dai_link_of(struct simple_util_priv *priv, ret = graph_parse_node(priv, cpu_ep, li, &is_single_links); if (ret < 0) - return ret; + goto end; ret = graph_parse_node(priv, codec_ep, li, NULL); if (ret < 0) - return ret; + goto end; snprintf(dai_name, sizeof(dai_name), "%s-%s", cpus->dai_name, codecs->dai_name); @@ -302,11 +309,11 @@ static int graph_dai_link_of(struct simple_util_priv *priv, ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name); if (ret < 0) - return ret; + goto end; li->link++; - - return 0; +end: + return graph_ret(priv, ret); } static inline bool parse_as_dpcm_link(struct simple_util_priv *priv, @@ -383,13 +390,13 @@ static int __graph_for_each_link(struct simple_util_priv *priv, } if (ret < 0) - return ret; + goto end; codec_port_old = codec_port; } } - - return 0; +end: + return graph_ret(priv, ret); } static int graph_for_each_link(struct simple_util_priv *priv, @@ -422,7 +429,7 @@ static int graph_for_each_link(struct simple_util_priv *priv, break; } - return ret; + return graph_ret(priv, ret); } static int graph_count_noml(struct simple_util_priv *priv, @@ -431,11 +438,10 @@ static int graph_count_noml(struct simple_util_priv *priv, struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; - if (li->link >= SNDRV_MAX_LINKS) { - dev_err(dev, "too many links\n"); - return -EINVAL; - } + if (li->link >= SNDRV_MAX_LINKS) + goto end; /* * DON'T REMOVE platforms @@ -450,8 +456,9 @@ static int graph_count_noml(struct simple_util_priv *priv, li->link += 1; /* 1xCPU-Codec */ dev_dbg(dev, "Count As Normal\n"); - - return 0; + ret = 0; +end: + return graph_ret(priv, ret); } static int graph_count_dpcm(struct simple_util_priv *priv, @@ -460,11 +467,10 @@ static int graph_count_dpcm(struct simple_util_priv *priv, struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; - if (li->link >= SNDRV_MAX_LINKS) { - dev_err(dev, "too many links\n"); - return -EINVAL; - } + if (li->link >= SNDRV_MAX_LINKS) + goto end; if (li->cpu) { /* @@ -483,8 +489,9 @@ static int graph_count_dpcm(struct simple_util_priv *priv, } dev_dbg(dev, "Count As DPCM\n"); - - return 0; + ret = 0; +end: + return graph_ret(priv, ret); } static int graph_get_dais_count(struct simple_util_priv *priv, @@ -544,40 +551,41 @@ static int graph_get_dais_count(struct simple_util_priv *priv, int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev) { struct snd_soc_card *card = simple_priv_to_card(priv); - int ret; + int ret = -ENOMEM; struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL); if (!li) - return -ENOMEM; + goto end; card->owner = THIS_MODULE; card->dev = dev; ret = graph_get_dais_count(priv, li); if (ret < 0) - return ret; + goto end; + ret = -EINVAL; if (!li->link) - return -EINVAL; + goto end; ret = simple_util_init_priv(priv, li); if (ret < 0) - return ret; + goto end; priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW); if (IS_ERR(priv->pa_gpio)) { ret = PTR_ERR(priv->pa_gpio); dev_err(dev, "failed to get amplifier gpio: %d\n", ret); - return ret; + goto end; } ret = simple_util_parse_widgets(card, NULL); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_routing(card, NULL); if (ret < 0) - return ret; + goto end; memset(li, 0, sizeof(*li)); ret = graph_for_each_link(priv, li, @@ -599,10 +607,9 @@ int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev) goto err; return 0; - err: simple_util_clean_reference(card); - +end: return dev_err_probe(dev, ret, "parse error\n"); } EXPORT_SYMBOL_GPL(audio_graph_parse_of); -- 2.51.0 From 8d83282e53185ec257a4ce08812e8fabee2c7212 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:36 +0000 Subject: [PATCH 08/16] ASoC: audio-graph-card2: use snd_soc_ret() We can use snd_soc_ret() to indicate error message when return. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c652ql8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 81 ++++++++++++++++----------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 945a16e6d691..5dcc78c551a2 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -234,6 +234,13 @@ enum graph_type { #define GRAPH_NODENAME_DPCM "dpcm" #define GRAPH_NODENAME_C2C "codec2codec" +#define graph_ret(priv, ret) _graph_ret(priv, __func__, ret) +static inline int _graph_ret(struct simple_util_priv *priv, + const char *func, int ret) +{ + return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); +} + #define ep_to_port(ep) of_get_parent(ep) static struct device_node *port_to_ports(struct device_node *port) { @@ -411,19 +418,19 @@ static int __graph_parse_node(struct simple_util_priv *priv, ret = graph_util_parse_dai(priv, ep, dlc, &is_single_links); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_tdm(ep, dai); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_tdm_width_map(priv, ep, dai); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_clk(dev, ep, dai, dlc); if (ret < 0) - return ret; + goto end; /* * set DAI Name @@ -488,11 +495,12 @@ static int __graph_parse_node(struct simple_util_priv *priv, simple_util_canonicalize_cpu(cpus, is_single_links); simple_util_canonicalize_platform(platforms, cpus); } - - return 0; +end: + return graph_ret(priv, ret); } -static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link, +static int graph_parse_node_multi_nm(struct simple_util_priv *priv, + struct snd_soc_dai_link *dai_link, int *nm_idx, int cpu_idx, struct device_node *mcpu_port) { @@ -534,10 +542,10 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link, struct device_node *mcodec_port_top __free(device_node) = ep_to_port(mcodec_ep_top); struct device_node *mcodec_ports __free(device_node) = port_to_ports(mcodec_port_top); int nm_max = max(dai_link->num_cpus, dai_link->num_codecs); - int ret = 0; + int ret = -EINVAL; if (cpu_idx > dai_link->num_cpus) - return -EINVAL; + goto end; for_each_of_graph_port_endpoint(mcpu_port, mcpu_ep_n) { int codec_idx = 0; @@ -578,8 +586,8 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link, if (ret < 0) break; } - - return ret; +end: + return graph_ret(priv, ret); } static int graph_parse_node_multi(struct simple_util_priv *priv, @@ -633,7 +641,7 @@ static int graph_parse_node_multi(struct simple_util_priv *priv, /* CPU:Codec = N:M */ if (is_cpu && dai_link->ch_maps) { - ret = graph_parse_node_multi_nm(dai_link, &nm_idx, idx, port); + ret = graph_parse_node_multi_nm(priv, dai_link, &nm_idx, idx, port); if (ret < 0) goto multi_err; } @@ -643,7 +651,7 @@ static int graph_parse_node_multi(struct simple_util_priv *priv, ret = -EINVAL; multi_err: - return ret; + return graph_ret(priv, ret); } static int graph_parse_node_single(struct simple_util_priv *priv, @@ -651,7 +659,7 @@ static int graph_parse_node_single(struct simple_util_priv *priv, struct device_node *ep, struct link_info *li, int is_cpu) { - return __graph_parse_node(priv, gtype, ep, li, is_cpu, 0); + return graph_ret(priv, __graph_parse_node(priv, gtype, ep, li, is_cpu, 0)); } static int graph_parse_node(struct simple_util_priv *priv, @@ -660,11 +668,14 @@ static int graph_parse_node(struct simple_util_priv *priv, struct link_info *li, int is_cpu) { struct device_node *port __free(device_node) = ep_to_port(ep); + int ret; if (graph_lnk_is_multi(port)) - return graph_parse_node_multi(priv, gtype, port, li, is_cpu); + ret = graph_parse_node_multi(priv, gtype, port, li, is_cpu); else - return graph_parse_node_single(priv, gtype, ep, li, is_cpu); + ret = graph_parse_node_single(priv, gtype, ep, li, is_cpu); + + return graph_ret(priv, ret); } static void graph_parse_daifmt(struct device_node *node, unsigned int *daifmt) @@ -842,18 +853,19 @@ int audio_graph2_link_normal(struct simple_util_priv *priv, */ ret = graph_parse_node(priv, GRAPH_NORMAL, codec_ep, li, 0); if (ret < 0) - return ret; + goto end; /* * call CPU, and set DAI Name */ ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_ep, li, 1); if (ret < 0) - return ret; + goto end; graph_link_init(priv, lnk, cpu_ep, codec_ep, li, 1); - return ret; +end: + return graph_ret(priv, ret); } EXPORT_SYMBOL_GPL(audio_graph2_link_normal); @@ -946,7 +958,7 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv, graph_link_init(priv, lnk, cpu_ep, codec_ep, li, is_cpu); - return ret; + return graph_ret(priv, ret); } EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm); @@ -992,8 +1004,13 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv, struct snd_soc_pcm_stream *c2c_conf; c2c_conf = devm_kzalloc(dev, sizeof(*c2c_conf), GFP_KERNEL); - if (!c2c_conf) - return ret; + if (!c2c_conf) { + /* + * Clang doesn't allow to use "goto end" before calling __free(), + * because it bypasses the initialization. Use graph_ret() directly. + */ + return graph_ret(priv, -ENOMEM); + } c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */ c2c_conf->rates = SNDRV_PCM_RATE_8000_384000; @@ -1019,18 +1036,18 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv, */ ret = graph_parse_node(priv, GRAPH_C2C, codec1_ep, li, 0); if (ret < 0) - return ret; + goto end; /* * call CPU, and set DAI Name */ ret = graph_parse_node(priv, GRAPH_C2C, codec0_ep, li, 1); if (ret < 0) - return ret; + goto end; graph_link_init(priv, lnk, codec0_ep, codec1_ep, li, 1); - - return ret; +end: + return graph_ret(priv, ret); } EXPORT_SYMBOL_GPL(audio_graph2_link_c2c); @@ -1078,7 +1095,7 @@ static int graph_link(struct simple_util_priv *priv, li->link++; err: - return ret; + return graph_ret(priv, ret); } static int graph_counter(struct device_node *lnk) @@ -1249,7 +1266,7 @@ static int graph_count(struct simple_util_priv *priv, li->link++; err: - return ret; + return graph_ret(priv, ret); } static int graph_for_each_link(struct simple_util_priv *priv, @@ -1266,7 +1283,7 @@ static int graph_for_each_link(struct simple_util_priv *priv, struct device_node *node = dev->of_node; struct device_node *lnk; enum graph_type gtype; - int rc, ret; + int rc, ret = 0; /* loop for all listed CPU port */ of_for_each_phandle(&it, rc, node, "links", NULL, 0) { @@ -1276,10 +1293,10 @@ static int graph_for_each_link(struct simple_util_priv *priv, ret = func(priv, hooks, gtype, lnk, li); if (ret < 0) - return ret; + break; } - return 0; + return graph_ret(priv, ret); } int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev, @@ -1355,7 +1372,7 @@ err: if (ret < 0) dev_err_probe(dev, ret, "parse error\n"); - return ret; + return graph_ret(priv, ret); } EXPORT_SYMBOL_GPL(audio_graph2_parse_of); -- 2.51.0 From e2ceac2f323625632f12dd5333092976298a0cde Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:55 +0530 Subject: [PATCH 09/16] ASoC: amd: ps: rename structure names, variable and other macros Rename macros and structure names, variable with ACP63 tag which are specific to ACP6.3 platform. Rename 'stream_index' and 'sdw_dma_data' variable names to avoid check patch warnings. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 66 ++++++++++++++++---------------- sound/soc/amd/ps/pci-ps.c | 64 +++++++++++++++---------------- sound/soc/amd/ps/ps-sdw-dma.c | 72 +++++++++++++++++------------------ 3 files changed, 101 insertions(+), 101 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index e54eabaa4d3e..01910273624b 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -13,13 +13,13 @@ #define ACP63_REG_END 0x125C000 #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 -#define ACP_PGFSM_CNTL_POWER_ON_MASK 1 -#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0 -#define ACP_PGFSM_STATUS_MASK 3 -#define ACP_POWERED_ON 0 -#define ACP_POWER_ON_IN_PROGRESS 1 -#define ACP_POWERED_OFF 2 -#define ACP_POWER_OFF_IN_PROGRESS 3 +#define ACP63_PGFSM_CNTL_POWER_ON_MASK 1 +#define ACP63_PGFSM_CNTL_POWER_OFF_MASK 0 +#define ACP63_PGFSM_STATUS_MASK 3 +#define ACP63_POWERED_ON 0 +#define ACP63_POWER_ON_IN_PROGRESS 1 +#define ACP63_POWERED_OFF 2 +#define ACP63_POWER_OFF_IN_PROGRESS 3 #define ACP_ERROR_MASK 0x20000000 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF @@ -60,7 +60,7 @@ #define AMD_SDW_MAX_MANAGERS 2 /* time in ms for acp timeout */ -#define ACP_TIMEOUT 500 +#define ACP63_TIMEOUT 500 #define ACP_SDW0_STAT BIT(21) #define ACP_SDW1_STAT BIT(2) @@ -72,13 +72,13 @@ #define ACP_AUDIO0_RX_THRESHOLD 0x1b #define ACP_AUDIO1_RX_THRESHOLD 0x19 #define ACP_AUDIO2_RX_THRESHOLD 0x17 -#define ACP_P1_AUDIO1_TX_THRESHOLD BIT(6) -#define ACP_P1_AUDIO1_RX_THRESHOLD BIT(5) -#define ACP_SDW_DMA_IRQ_MASK 0x1F800000 -#define ACP_P1_SDW_DMA_IRQ_MASK 0x60 +#define ACP63_P1_AUDIO1_TX_THRESHOLD BIT(6) +#define ACP63_P1_AUDIO1_RX_THRESHOLD BIT(5) +#define ACP63_SDW_DMA_IRQ_MASK 0x1F800000 +#define ACP63_P1_SDW_DMA_IRQ_MASK 0x60 #define ACP63_SDW0_DMA_MAX_STREAMS 6 #define ACP63_SDW1_DMA_MAX_STREAMS 2 -#define ACP_P1_AUDIO_TX_THRESHOLD 6 +#define ACP63_P1_AUDIO_TX_THRESHOLD 6 /* * Below entries describes SDW0 instance DMA stream id and DMA irq bit mapping @@ -91,8 +91,8 @@ * 4 (SDW0_AUDIO1_RX) 25 * 5 (SDW0_AUDIO2_RX) 23 */ -#define SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) -#define SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) +#define ACP63_SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) +#define ACP63_SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) /* * Below entries describes SDW1 instance DMA stream id and DMA irq bit mapping @@ -101,7 +101,7 @@ * 0 (SDW1_AUDIO1_TX) 6 * 1 (SDW1_AUDIO1_RX) 5 */ -#define SDW1_DMA_IRQ_MASK(i) (ACP_P1_AUDIO_TX_THRESHOLD - (i)) +#define ACP63_SDW1_DMA_IRQ_MASK(i) (ACP63_P1_AUDIO_TX_THRESHOLD - (i)) #define ACP_DELAY_US 5 #define ACP_SDW_RING_BUFF_ADDR_OFFSET (128 * 1024) @@ -148,18 +148,18 @@ enum acp_config { ACP_CONFIG_15, }; -enum amd_sdw0_channel { - ACP_SDW0_AUDIO0_TX = 0, - ACP_SDW0_AUDIO1_TX, - ACP_SDW0_AUDIO2_TX, - ACP_SDW0_AUDIO0_RX, - ACP_SDW0_AUDIO1_RX, - ACP_SDW0_AUDIO2_RX, +enum amd_acp63_sdw0_channel { + ACP63_SDW0_AUDIO0_TX = 0, + ACP63_SDW0_AUDIO1_TX, + ACP63_SDW0_AUDIO2_TX, + ACP63_SDW0_AUDIO0_RX, + ACP63_SDW0_AUDIO1_RX, + ACP63_SDW0_AUDIO2_RX, }; -enum amd_sdw1_channel { - ACP_SDW1_AUDIO1_TX, - ACP_SDW1_AUDIO1_RX, +enum amd_acp63_sdw1_channel { + ACP63_SDW1_AUDIO1_TX, + ACP63_SDW1_AUDIO1_RX, }; struct pdm_stream_instance { @@ -180,8 +180,8 @@ struct pdm_dev_data { struct sdw_dma_dev_data { void __iomem *acp_base; struct mutex *acp_lock; /* used to protect acp common register access */ - struct snd_pcm_substream *sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; - struct snd_pcm_substream *sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp63_sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp63_sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; }; struct acp_sdw_dma_stream { @@ -232,8 +232,10 @@ struct sdw_dma_ring_buf_reg { * @addr: pci ioremap address * @reg_range: ACP reigister range * @acp_rev: ACP PCI revision id - * @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance - * @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance + * @acp63_sdw0-dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire + * manager-SW0 instance + * @acp63_sdw_dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire + * manager-SW1 instance */ struct acp63_dev_data { @@ -256,8 +258,8 @@ struct acp63_dev_data { u32 addr; u32 reg_range; u32 acp_rev; - u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; - u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; + u16 acp63_sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; + u16 acp63_sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; }; int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 8b556950b855..f5beb7f14913 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -30,10 +30,10 @@ static int acp63_power_on(void __iomem *acp_base) if (!val) return val; - if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS) - writel(ACP_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS) + writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); - return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP_TIMEOUT); + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT); } static int acp63_reset(void __iomem *acp_base) @@ -45,13 +45,13 @@ static int acp63_reset(void __iomem *acp_base) ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, - DELAY_US, ACP_TIMEOUT); + DELAY_US, ACP63_TIMEOUT); if (ret) return ret; writel(0, acp_base + ACP_SOFT_RESET); - return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT); + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT); } static void acp63_enable_interrupts(void __iomem *acp_base) @@ -104,24 +104,24 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) static irqreturn_t acp63_irq_thread(int irq, void *context) { - struct sdw_dma_dev_data *sdw_dma_data; + struct sdw_dma_dev_data *sdw_data; struct acp63_dev_data *adata = context; - u32 stream_index; + u32 stream_id; - sdw_dma_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); + sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); - for (stream_index = 0; stream_index < ACP63_SDW0_DMA_MAX_STREAMS; stream_index++) { - if (adata->sdw0_dma_intr_stat[stream_index]) { - if (sdw_dma_data->sdw0_dma_stream[stream_index]) - snd_pcm_period_elapsed(sdw_dma_data->sdw0_dma_stream[stream_index]); - adata->sdw0_dma_intr_stat[stream_index] = 0; + for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw0_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw0_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]); + adata->acp63_sdw0_dma_intr_stat[stream_id] = 0; } } - for (stream_index = 0; stream_index < ACP63_SDW1_DMA_MAX_STREAMS; stream_index++) { - if (adata->sdw1_dma_intr_stat[stream_index]) { - if (sdw_dma_data->sdw1_dma_stream[stream_index]) - snd_pcm_period_elapsed(sdw_dma_data->sdw1_dma_stream[stream_index]); - adata->sdw1_dma_intr_stat[stream_index] = 0; + for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw1_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw1_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]); + adata->acp63_sdw1_dma_intr_stat[stream_id] = 0; } } return IRQ_HANDLED; @@ -180,48 +180,48 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) snd_pcm_period_elapsed(ps_pdm_data->capture_stream); irq_flag = 1; } - if (ext_intr_stat & ACP_SDW_DMA_IRQ_MASK) { + if (ext_intr_stat & ACP63_SDW_DMA_IRQ_MASK) { for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) { if (ext_intr_stat & BIT(index)) { writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); switch (index) { case ACP_AUDIO0_TX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO0_TX; + stream_id = ACP63_SDW0_AUDIO0_TX; break; case ACP_AUDIO1_TX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO1_TX; + stream_id = ACP63_SDW0_AUDIO1_TX; break; case ACP_AUDIO2_TX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO2_TX; + stream_id = ACP63_SDW0_AUDIO2_TX; break; case ACP_AUDIO0_RX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO0_RX; + stream_id = ACP63_SDW0_AUDIO0_RX; break; case ACP_AUDIO1_RX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO1_RX; + stream_id = ACP63_SDW0_AUDIO1_RX; break; case ACP_AUDIO2_RX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO2_RX; + stream_id = ACP63_SDW0_AUDIO2_RX; break; } - adata->sdw0_dma_intr_stat[stream_id] = 1; + adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; sdw_dma_irq_flag = 1; } } } - if (ext_intr_stat1 & ACP_P1_AUDIO1_RX_THRESHOLD) { - writel(ACP_P1_AUDIO1_RX_THRESHOLD, + if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_RX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->sdw1_dma_intr_stat[ACP_SDW1_AUDIO1_RX] = 1; + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; sdw_dma_irq_flag = 1; } - if (ext_intr_stat1 & ACP_P1_AUDIO1_TX_THRESHOLD) { - writel(ACP_P1_AUDIO1_TX_THRESHOLD, + if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_TX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->sdw1_dma_intr_stat[ACP_SDW1_AUDIO1_TX] = 1; + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; sdw_dma_irq_flag = 1; } diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index b602cca92b8b..878683619a05 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -18,7 +18,7 @@ #define DRV_NAME "amd_ps_sdw_dma" -static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { +static struct sdw_dma_ring_buf_reg acp63_sdw0_dma_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { {ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE, ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, @@ -44,7 +44,7 @@ static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STRE * For TX/RX streams DMA registers programming for SDW1 instance, it uses ACP_P1_AUDIO1 register * set as per hardware register documentation */ -static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { +static struct sdw_dma_ring_buf_reg acp63_sdw1_dma_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { {ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE, ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR, ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE, @@ -55,7 +55,7 @@ static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg[ACP63_SDW1_DMA_MAX_STRE ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, }; -static u32 sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { +static u32 acp63_sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { ACP_SW0_AUDIO0_TX_EN, ACP_SW0_AUDIO1_TX_EN, ACP_SW0_AUDIO2_TX_EN, @@ -70,7 +70,7 @@ static u32 sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { * it uses ACP_SW1_AUDIO1_TX_EN and ACP_SW1_AUDIO1_RX_EN registers * as per hardware register documentation. */ -static u32 sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { +static u32 acp63_sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { ACP_SW1_AUDIO1_TX_EN, ACP_SW1_AUDIO1_RX_EN, }; @@ -117,8 +117,8 @@ static const struct snd_pcm_hardware acp63_sdw_hardware_capture = { static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, bool enable) { u32 ext_intr_cntl, ext_intr_cntl1; - u32 irq_mask = ACP_SDW_DMA_IRQ_MASK; - u32 irq_mask1 = ACP_P1_SDW_DMA_IRQ_MASK; + u32 irq_mask = ACP63_SDW_DMA_IRQ_MASK; + u32 irq_mask1 = ACP63_P1_SDW_DMA_IRQ_MASK; if (enable) { ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL); @@ -182,18 +182,18 @@ static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, switch (manager_instance) { case ACP_SDW0: - reg_dma_size = sdw0_dma_ring_buf_reg[stream_id].reg_dma_size; - reg_fifo_addr = sdw0_dma_ring_buf_reg[stream_id].reg_fifo_addr; - reg_fifo_size = sdw0_dma_ring_buf_reg[stream_id].reg_fifo_size; - reg_ring_buf_size = sdw0_dma_ring_buf_reg[stream_id].reg_ring_buf_size; - reg_ring_buf_addr = sdw0_dma_ring_buf_reg[stream_id].reg_ring_buf_addr; + reg_dma_size = acp63_sdw0_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp63_sdw0_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp63_sdw0_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_addr; break; case ACP_SDW1: - reg_dma_size = sdw1_dma_ring_buf_reg[stream_id].reg_dma_size; - reg_fifo_addr = sdw1_dma_ring_buf_reg[stream_id].reg_fifo_addr; - reg_fifo_size = sdw1_dma_ring_buf_reg[stream_id].reg_fifo_size; - reg_ring_buf_size = sdw1_dma_ring_buf_reg[stream_id].reg_ring_buf_size; - reg_ring_buf_addr = sdw1_dma_ring_buf_reg[stream_id].reg_ring_buf_addr; + reg_dma_size = acp63_sdw1_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp63_sdw1_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp63_sdw1_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_addr; break; default: return -EINVAL; @@ -267,19 +267,19 @@ static int acp63_sdw_dma_hw_params(struct snd_soc_component *component, stream_id = stream->stream_id; switch (stream->instance) { case ACP_SDW0: - sdw_data->sdw0_dma_stream[stream_id] = substream; - water_mark_size_reg = sdw0_dma_ring_buf_reg[stream_id].water_mark_size_reg; + sdw_data->acp63_sdw0_dma_stream[stream_id] = substream; + water_mark_size_reg = acp63_sdw0_dma_reg[stream_id].water_mark_size_reg; acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - irq_mask = BIT(SDW0_DMA_TX_IRQ_MASK(stream_id)); + irq_mask = BIT(ACP63_SDW0_DMA_TX_IRQ_MASK(stream_id)); else - irq_mask = BIT(SDW0_DMA_RX_IRQ_MASK(stream_id)); + irq_mask = BIT(ACP63_SDW0_DMA_RX_IRQ_MASK(stream_id)); break; case ACP_SDW1: - sdw_data->sdw1_dma_stream[stream_id] = substream; + sdw_data->acp63_sdw1_dma_stream[stream_id] = substream; acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1; - water_mark_size_reg = sdw1_dma_ring_buf_reg[stream_id].water_mark_size_reg; - irq_mask = BIT(SDW1_DMA_IRQ_MASK(stream_id)); + water_mark_size_reg = acp63_sdw1_dma_reg[stream_id].water_mark_size_reg; + irq_mask = BIT(ACP63_SDW1_DMA_IRQ_MASK(stream_id)); break; default: return -EINVAL; @@ -310,12 +310,12 @@ static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __io byte_count.bytescount = 0; switch (stream->instance) { case ACP_SDW0: - pos_low_reg = sdw0_dma_ring_buf_reg[stream->stream_id].pos_low_reg; - pos_high_reg = sdw0_dma_ring_buf_reg[stream->stream_id].pos_high_reg; + pos_low_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_high_reg; break; case ACP_SDW1: - pos_low_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_low_reg; - pos_high_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_high_reg; + pos_low_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_high_reg; break; default: goto POINTER_RETURN_BYTES; @@ -369,10 +369,10 @@ static int acp63_sdw_dma_close(struct snd_soc_component *component, return -EINVAL; switch (stream->instance) { case ACP_SDW0: - sdw_data->sdw0_dma_stream[stream->stream_id] = NULL; + sdw_data->acp63_sdw0_dma_stream[stream->stream_id] = NULL; break; case ACP_SDW1: - sdw_data->sdw1_dma_stream[stream->stream_id] = NULL; + sdw_data->acp63_sdw1_dma_stream[stream->stream_id] = NULL; break; default: return -EINVAL; @@ -395,10 +395,10 @@ static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream, stream_id = stream->stream_id; switch (stream->instance) { case ACP_SDW0: - sdw_dma_en_reg = sdw0_dma_enable_reg[stream_id]; + sdw_dma_en_reg = acp63_sdw0_dma_enable_reg[stream_id]; break; case ACP_SDW1: - sdw_dma_en_reg = sdw1_dma_enable_reg[stream_id]; + sdw_dma_en_reg = acp63_sdw1_dma_enable_reg[stream_id]; break; default: return -EINVAL; @@ -512,13 +512,11 @@ static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) for (index = 0; index < stream_count; index++) { if (instance == ACP_SDW0) { - substream = sdw_data->sdw0_dma_stream[index]; - water_mark_size_reg = - sdw0_dma_ring_buf_reg[index].water_mark_size_reg; + substream = sdw_data->acp63_sdw0_dma_stream[index]; + water_mark_size_reg = acp63_sdw0_dma_reg[index].water_mark_size_reg; } else { - substream = sdw_data->sdw1_dma_stream[index]; - water_mark_size_reg = - sdw1_dma_ring_buf_reg[index].water_mark_size_reg; + substream = sdw_data->acp63_sdw1_dma_stream[index]; + water_mark_size_reg = acp63_sdw1_dma_reg[index].water_mark_size_reg; } if (substream && substream->runtime) { -- 2.51.0 From 4b36a47e2d989b98953dbfb1e97da0f0169f5086 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:56 +0530 Subject: [PATCH 10/16] ASoC: amd: ps: use macro for ACP6.3 pci revision id Use macro for ACP6.3 PCI revision id instead of hard coded value. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 1 + sound/soc/amd/ps/pci-ps.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 01910273624b..8f3a597f658b 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -11,6 +11,7 @@ #define ACP_DEVICE_ID 0x15E2 #define ACP63_REG_START 0x1240000 #define ACP63_REG_END 0x125C000 +#define ACP63_PCI_REV 0x63 #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 #define ACP63_PGFSM_CNTL_POWER_ON_MASK 1 diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index f5beb7f14913..9cc66a807ad9 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -562,7 +562,7 @@ static int snd_acp63_probe(struct pci_dev *pci, /* Pink Sardine device check */ switch (pci->revision) { - case 0x63: + case ACP63_PCI_REV: break; default: dev_dbg(&pci->dev, "acp63 pci device not found\n"); -- 2.51.0 From db746fff89a14419379226ce0df8b94f472cf38c Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:57 +0530 Subject: [PATCH 11/16] ASoC: amd: ps: add acp pci driver hw_ops for acp6.3 platform Add ACP6.3 platform specific PCI driver hw_ops for acp init/de-init sequence. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-4-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/Makefile | 2 +- sound/soc/amd/ps/acp63.h | 32 ++++++++++ sound/soc/amd/ps/pci-ps.c | 118 +++++++++-------------------------- sound/soc/amd/ps/ps-common.c | 104 ++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 89 deletions(-) create mode 100644 sound/soc/amd/ps/ps-common.c diff --git a/sound/soc/amd/ps/Makefile b/sound/soc/amd/ps/Makefile index b5efb1c5382c..778ee4726389 100644 --- a/sound/soc/amd/ps/Makefile +++ b/sound/soc/amd/ps/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only # Pink Sardine platform Support -snd-pci-ps-y := pci-ps.o +snd-pci-ps-y := pci-ps.o ps-common.o snd-ps-pdm-dma-y := ps-pdm-dma.o snd-soc-ps-mach-y := ps-mach.o snd-ps-sdw-dma-y := ps-sdw-dma.o diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 8f3a597f658b..ec22a7dad6ac 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -130,6 +130,8 @@ #define SDW_MAX_BUFFER (SDW_PLAYBACK_MAX_PERIOD_SIZE * SDW_PLAYBACK_MAX_NUM_PERIODS) #define SDW_MIN_BUFFER SDW_MAX_BUFFER +#define ACP_HW_OPS(acp_data, cb) ((acp_data)->hw_ops->cb) + enum acp_config { ACP_CONFIG_0 = 0, ACP_CONFIG_1, @@ -213,10 +215,23 @@ struct sdw_dma_ring_buf_reg { u32 pos_high_reg; }; +struct acp63_dev_data; + +/** + * struct acp_hw_ops - ACP PCI driver platform specific ops + * @acp_init: ACP initialization + * @acp_deinit: ACP de-initialization + */ +struct acp_hw_ops { + int (*acp_init)(void __iomem *acp_base, struct device *dev); + int (*acp_deinit)(void __iomem *acp_base, struct device *dev); +}; + /** * struct acp63_dev_data - acp pci driver context * @acp63_base: acp mmio base * @res: resource + * @hw_ops: ACP pci driver platform-specific ops * @pdm_dev: ACP PDM controller platform device * @dmic_codec: platform device for DMIC Codec * sdw_dma_dev: platform device for SoundWire DMA controller @@ -242,6 +257,7 @@ struct sdw_dma_ring_buf_reg { struct acp63_dev_data { void __iomem *acp63_base; struct resource *res; + struct acp_hw_ops *hw_ops; struct platform_device *pdm_dev; struct platform_device *dmic_codec_dev; struct platform_device *sdw_dma_dev; @@ -263,4 +279,20 @@ struct acp63_dev_data { u16 acp63_sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; }; +void acp63_hw_init_ops(struct acp_hw_ops *hw_ops); + +static inline int acp_hw_init(struct acp63_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_init) + return ACP_HW_OPS(adata, acp_init)(adata->acp63_base, dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_deinit(struct acp63_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_deinit) + return ACP_HW_OPS(adata, acp_deinit)(adata->acp63_base, dev); + return -EOPNOTSUPP; +} + int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 9cc66a807ad9..120bab1844bb 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -21,87 +21,6 @@ #include "acp63.h" -static int acp63_power_on(void __iomem *acp_base) -{ - u32 val; - - val = readl(acp_base + ACP_PGFSM_STATUS); - - if (!val) - return val; - - if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS) - writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); - - return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT); -} - -static int acp63_reset(void __iomem *acp_base) -{ - u32 val; - int ret; - - writel(1, acp_base + ACP_SOFT_RESET); - - ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, - val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, - DELAY_US, ACP63_TIMEOUT); - if (ret) - return ret; - - writel(0, acp_base + ACP_SOFT_RESET); - - return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT); -} - -static void acp63_enable_interrupts(void __iomem *acp_base) -{ - writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); - writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL); -} - -static void acp63_disable_interrupts(void __iomem *acp_base) -{ - writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT); - writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); - writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); -} - -static int acp63_init(void __iomem *acp_base, struct device *dev) -{ - int ret; - - ret = acp63_power_on(acp_base); - if (ret) { - dev_err(dev, "ACP power on failed\n"); - return ret; - } - writel(0x01, acp_base + ACP_CONTROL); - ret = acp63_reset(acp_base); - if (ret) { - dev_err(dev, "ACP reset failed\n"); - return ret; - } - acp63_enable_interrupts(acp_base); - writel(0, acp_base + ACP_ZSC_DSP_CTRL); - return 0; -} - -static int acp63_deinit(void __iomem *acp_base, struct device *dev) -{ - int ret; - - acp63_disable_interrupts(acp_base); - ret = acp63_reset(acp_base); - if (ret) { - dev_err(dev, "ACP reset failed\n"); - return ret; - } - writel(0, acp_base + ACP_CONTROL); - writel(1, acp_base + ACP_ZSC_DSP_CTRL); - return 0; -} - static irqreturn_t acp63_irq_thread(int irq, void *context) { struct sdw_dma_dev_data *sdw_data; @@ -540,11 +459,29 @@ unregister_dmic_codec_dev: unregister_pdm_dev: platform_device_unregister(adata->pdm_dev); de_init: - if (acp63_deinit(adata->acp63_base, &pci->dev)) + if (acp_hw_deinit(adata, &pci->dev)) dev_err(&pci->dev, "ACP de-init failed\n"); return ret; } +static int acp_hw_init_ops(struct acp63_dev_data *adata, struct pci_dev *pci) +{ + adata->hw_ops = devm_kzalloc(&pci->dev, sizeof(struct acp_hw_ops), + GFP_KERNEL); + if (!adata->hw_ops) + return -ENOMEM; + + switch (adata->acp_rev) { + case ACP63_PCI_REV: + acp63_hw_init_ops(adata->hw_ops); + break; + default: + dev_err(&pci->dev, "ACP device not found\n"); + return -ENODEV; + } + return 0; +} + static int snd_acp63_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -598,7 +535,12 @@ static int snd_acp63_probe(struct pci_dev *pci, pci_set_master(pci); pci_set_drvdata(pci, adata); mutex_init(&adata->acp_lock); - ret = acp63_init(adata->acp63_base, &pci->dev); + ret = acp_hw_init_ops(adata, pci); + if (ret) { + dev_err(&pci->dev, "ACP hw ops init failed\n"); + goto release_regions; + } + ret = acp_hw_init(adata, &pci->dev); if (ret) goto release_regions; ret = devm_request_threaded_irq(&pci->dev, pci->irq, acp63_irq_handler, @@ -632,7 +574,7 @@ skip_pdev_creation: pm_runtime_allow(&pci->dev); return 0; de_init: - if (acp63_deinit(adata->acp63_base, &pci->dev)) + if (acp_hw_deinit(adata, &pci->dev)) dev_err(&pci->dev, "ACP de-init failed\n"); release_regions: pci_release_regions(pci); @@ -677,7 +619,7 @@ static int __maybe_unused snd_acp63_suspend(struct device *dev) return 0; } } - ret = acp63_deinit(adata->acp63_base, dev); + ret = acp_hw_deinit(adata, dev); if (ret) dev_err(dev, "ACP de-init failed\n"); @@ -694,7 +636,7 @@ static int __maybe_unused snd_acp63_runtime_resume(struct device *dev) writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); return 0; } - ret = acp63_init(adata->acp63_base, dev); + ret = acp_hw_init(adata, dev); if (ret) { dev_err(dev, "ACP init failed\n"); return ret; @@ -716,7 +658,7 @@ static int __maybe_unused snd_acp63_resume(struct device *dev) return 0; } - ret = acp63_init(adata->acp63_base, dev); + ret = acp_hw_deinit(adata, dev); if (ret) dev_err(dev, "ACP init failed\n"); @@ -744,7 +686,7 @@ static void snd_acp63_remove(struct pci_dev *pci) } if (adata->mach_dev) platform_device_unregister(adata->mach_dev); - ret = acp63_deinit(adata->acp63_base, &pci->dev); + ret = acp_hw_deinit(adata, &pci->dev); if (ret) dev_err(&pci->dev, "ACP de-init failed\n"); pm_runtime_forbid(&pci->dev); diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c new file mode 100644 index 000000000000..771249a76537 --- /dev/null +++ b/sound/soc/amd/ps/ps-common.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD ACP PCI driver callback routines for ACP6.3, ACP7.0 & ACP7.1 + * platforms. + * + * Copyright 2025 Advanced Micro Devices, Inc. + * Authors: Vijendar Mukunda + */ + +#include +#include +#include +#include +#include +#include + +#include "acp63.h" + +static int acp63_power_on(void __iomem *acp_base) +{ + u32 val; + + val = readl(acp_base + ACP_PGFSM_STATUS); + + if (!val) + return val; + + if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS) + writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT); +} + +static int acp63_reset(void __iomem *acp_base) +{ + u32 val; + int ret; + + writel(1, acp_base + ACP_SOFT_RESET); + + ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, + val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, + DELAY_US, ACP63_TIMEOUT); + if (ret) + return ret; + + writel(0, acp_base + ACP_SOFT_RESET); + + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT); +} + +static void acp63_enable_interrupts(void __iomem *acp_base) +{ + writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); + writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void acp63_disable_interrupts(void __iomem *acp_base) +{ + writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT); + writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); + writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static int acp63_init(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp63_power_on(acp_base); + if (ret) { + dev_err(dev, "ACP power on failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_CONTROL); + ret = acp63_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + acp63_enable_interrupts(acp_base); + writel(0, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static int acp63_deinit(void __iomem *acp_base, struct device *dev) +{ + int ret; + + acp63_disable_interrupts(acp_base); + ret = acp63_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0, acp_base + ACP_CONTROL); + writel(1, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) +{ + hw_ops->acp_init = acp63_init; + hw_ops->acp_deinit = acp63_deinit; +} -- 2.51.0 From 491628388005a26c02d6827e649284357daec213 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:58 +0530 Subject: [PATCH 12/16] ASoC: amd: ps: add callback functions for acp pci driver pm ops Add acp pci driver pm ops related callback functions for ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-5-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 44 ++++++++++++++++++ sound/soc/amd/ps/pci-ps.c | 82 ++++------------------------------ sound/soc/amd/ps/ps-common.c | 86 ++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 74 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index ec22a7dad6ac..4e3f7eaac040 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -221,10 +221,18 @@ struct acp63_dev_data; * struct acp_hw_ops - ACP PCI driver platform specific ops * @acp_init: ACP initialization * @acp_deinit: ACP de-initialization + * acp_suspend: ACP system level suspend callback + * acp_resume: ACP system level resume callback + * acp_suspend_runtime: ACP runtime suspend callback + * acp_resume_runtime: ACP runtime resume callback */ struct acp_hw_ops { int (*acp_init)(void __iomem *acp_base, struct device *dev); int (*acp_deinit)(void __iomem *acp_base, struct device *dev); + int (*acp_suspend)(struct device *dev); + int (*acp_resume)(struct device *dev); + int (*acp_suspend_runtime)(struct device *dev); + int (*acp_resume_runtime)(struct device *dev); }; /** @@ -295,4 +303,40 @@ static inline int acp_hw_deinit(struct acp63_dev_data *adata, struct device *dev return -EOPNOTSUPP; } +static inline int acp_hw_suspend(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend) + return ACP_HW_OPS(adata, acp_suspend)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_resume(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume) + return ACP_HW_OPS(adata, acp_resume)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_suspend_runtime(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend_runtime) + return ACP_HW_OPS(adata, acp_suspend_runtime)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_runtime_resume(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume_runtime) + return ACP_HW_OPS(adata, acp_resume_runtime)(dev); + return -EOPNOTSUPP; +} + int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 120bab1844bb..a37fb6172958 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -584,90 +584,24 @@ disable_pci: return ret; } -static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata) +static int __maybe_unused snd_acp_suspend(struct device *dev) { - u32 sdw0_en, sdw1_en; - - sdw0_en = readl(adata->acp63_base + ACP_SW0_EN); - sdw1_en = readl(adata->acp63_base + ACP_SW1_EN); - return (sdw0_en || sdw1_en); + return acp_hw_suspend(dev); } -static void handle_acp63_sdw_pme_event(struct acp63_dev_data *adata) +static int __maybe_unused snd_acp_runtime_resume(struct device *dev) { - u32 val; - - val = readl(adata->acp63_base + ACP_SW0_WAKE_EN); - if (val && adata->sdw->pdev[0]) - pm_request_resume(&adata->sdw->pdev[0]->dev); - - val = readl(adata->acp63_base + ACP_SW1_WAKE_EN); - if (val && adata->sdw->pdev[1]) - pm_request_resume(&adata->sdw->pdev[1]->dev); + return acp_hw_runtime_resume(dev); } -static int __maybe_unused snd_acp63_suspend(struct device *dev) +static int __maybe_unused snd_acp_resume(struct device *dev) { - struct acp63_dev_data *adata; - int ret; - - adata = dev_get_drvdata(dev); - if (adata->is_sdw_dev) { - adata->sdw_en_stat = check_acp_sdw_enable_status(adata); - if (adata->sdw_en_stat) { - writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL); - return 0; - } - } - ret = acp_hw_deinit(adata, dev); - if (ret) - dev_err(dev, "ACP de-init failed\n"); - - return ret; -} - -static int __maybe_unused snd_acp63_runtime_resume(struct device *dev) -{ - struct acp63_dev_data *adata; - int ret; - - adata = dev_get_drvdata(dev); - if (adata->sdw_en_stat) { - writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); - return 0; - } - ret = acp_hw_init(adata, dev); - if (ret) { - dev_err(dev, "ACP init failed\n"); - return ret; - } - - if (!adata->sdw_en_stat) - handle_acp63_sdw_pme_event(adata); - return 0; -} - -static int __maybe_unused snd_acp63_resume(struct device *dev) -{ - struct acp63_dev_data *adata; - int ret; - - adata = dev_get_drvdata(dev); - if (adata->sdw_en_stat) { - writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); - return 0; - } - - ret = acp_hw_deinit(adata, dev); - if (ret) - dev_err(dev, "ACP init failed\n"); - - return ret; + return acp_hw_resume(dev); } static const struct dev_pm_ops acp63_pm_ops = { - SET_RUNTIME_PM_OPS(snd_acp63_suspend, snd_acp63_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(snd_acp63_suspend, snd_acp63_resume) + SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) }; static void snd_acp63_remove(struct pci_dev *pci) diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index 771249a76537..7643f321be37 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "acp63.h" @@ -97,8 +98,93 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) return 0; } +static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata) +{ + u32 sdw0_en, sdw1_en; + + sdw0_en = readl(adata->acp63_base + ACP_SW0_EN); + sdw1_en = readl(adata->acp63_base + ACP_SW1_EN); + return (sdw0_en || sdw1_en); +} + +static void handle_acp63_sdw_pme_event(struct acp63_dev_data *adata) +{ + u32 val; + + val = readl(adata->acp63_base + ACP_SW0_WAKE_EN); + if (val && adata->sdw->pdev[0]) + pm_request_resume(&adata->sdw->pdev[0]->dev); + + val = readl(adata->acp63_base + ACP_SW1_WAKE_EN); + if (val && adata->sdw->pdev[1]) + pm_request_resume(&adata->sdw->pdev[1]->dev); +} + +static int __maybe_unused snd_acp63_suspend(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->is_sdw_dev) { + adata->sdw_en_stat = check_acp_sdw_enable_status(adata); + if (adata->sdw_en_stat) { + writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL); + return 0; + } + } + ret = acp_hw_deinit(adata, dev); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + + return ret; +} + +static int __maybe_unused snd_acp63_runtime_resume(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->sdw_en_stat) { + writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); + return 0; + } + ret = acp_hw_init(adata, dev); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + + if (!adata->sdw_en_stat) + handle_acp63_sdw_pme_event(adata); + return 0; +} + +static int __maybe_unused snd_acp63_resume(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->sdw_en_stat) { + writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); + return 0; + } + + ret = acp_hw_init(adata, dev); + if (ret) + dev_err(dev, "ACP init failed\n"); + + return ret; +} + void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) { hw_ops->acp_init = acp63_init; hw_ops->acp_deinit = acp63_deinit; + hw_ops->acp_suspend = snd_acp63_suspend; + hw_ops->acp_resume = snd_acp63_resume; + hw_ops->acp_suspend_runtime = snd_acp63_suspend; + hw_ops->acp_resume_runtime = snd_acp63_runtime_resume; } -- 2.51.0 From 6547577e94ae3d9f8ff30d3267fe7ec394e3b20d Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:59 +0530 Subject: [PATCH 13/16] ASoC: amd: ps: add callback to read acp pin configuration Add pci driver callback to read acp pin configuration for ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-6-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 8 ++++++++ sound/soc/amd/ps/pci-ps.c | 26 +------------------------- sound/soc/amd/ps/ps-common.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 4e3f7eaac040..a918a988e4d8 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -221,6 +221,7 @@ struct acp63_dev_data; * struct acp_hw_ops - ACP PCI driver platform specific ops * @acp_init: ACP initialization * @acp_deinit: ACP de-initialization + * @acp_get_config: function to read the acp pin configuration * acp_suspend: ACP system level suspend callback * acp_resume: ACP system level resume callback * acp_suspend_runtime: ACP runtime suspend callback @@ -229,6 +230,7 @@ struct acp63_dev_data; struct acp_hw_ops { int (*acp_init)(void __iomem *acp_base, struct device *dev); int (*acp_deinit)(void __iomem *acp_base, struct device *dev); + void (*acp_get_config)(struct pci_dev *pci, struct acp63_dev_data *acp_data); int (*acp_suspend)(struct device *dev); int (*acp_resume)(struct device *dev); int (*acp_suspend_runtime)(struct device *dev); @@ -303,6 +305,12 @@ static inline int acp_hw_deinit(struct acp63_dev_data *adata, struct device *dev return -EOPNOTSUPP; } +static inline void acp_hw_get_config(struct pci_dev *pci, struct acp63_dev_data *adata) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_get_config) + ACP_HW_OPS(adata, acp_get_config)(pci, adata); +} + static inline int acp_hw_suspend(struct device *dev) { struct acp63_dev_data *adata = dev_get_drvdata(dev); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index a37fb6172958..96399acf906c 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -299,7 +299,6 @@ static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *a 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; @@ -309,30 +308,7 @@ static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *a wov_en = true; dmic_en = false; - config = readl(acp_data->acp63_base + ACP_PIN_CONFIG); - switch (config) { - case ACP_CONFIG_4: - case ACP_CONFIG_5: - case ACP_CONFIG_10: - case ACP_CONFIG_11: - acp_data->is_pdm_config = true; - break; - case ACP_CONFIG_2: - case ACP_CONFIG_3: - acp_data->is_sdw_config = true; - break; - case ACP_CONFIG_6: - case ACP_CONFIG_7: - case ACP_CONFIG_12: - case ACP_CONFIG_8: - case ACP_CONFIG_13: - case ACP_CONFIG_14: - acp_data->is_pdm_config = true; - acp_data->is_sdw_config = true; - break; - default: - break; - } + acp_hw_get_config(pci, acp_data); if (acp_data->is_pdm_config) { pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0); diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index 7643f321be37..30e9e5fe034b 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,37 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) return 0; } +static void acp63_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data) +{ + u32 config; + + config = readl(acp_data->acp63_base + ACP_PIN_CONFIG); + dev_dbg(&pci->dev, "ACP config value: %d\n", config); + switch (config) { + case ACP_CONFIG_4: + case ACP_CONFIG_5: + case ACP_CONFIG_10: + case ACP_CONFIG_11: + acp_data->is_pdm_config = true; + break; + case ACP_CONFIG_2: + case ACP_CONFIG_3: + acp_data->is_sdw_config = true; + break; + case ACP_CONFIG_6: + case ACP_CONFIG_7: + case ACP_CONFIG_12: + case ACP_CONFIG_8: + case ACP_CONFIG_13: + case ACP_CONFIG_14: + acp_data->is_pdm_config = true; + acp_data->is_sdw_config = true; + break; + default: + break; + } +} + static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata) { u32 sdw0_en, sdw1_en; @@ -183,6 +215,7 @@ void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) { hw_ops->acp_init = acp63_init; hw_ops->acp_deinit = acp63_deinit; + hw_ops->acp_get_config = acp63_get_config; hw_ops->acp_suspend = snd_acp63_suspend; hw_ops->acp_resume = snd_acp63_resume; hw_ops->acp_suspend_runtime = snd_acp63_suspend; -- 2.51.0 From 0a27b2d7a224326fab543ca586d501fe1857b655 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:00 +0530 Subject: [PATCH 14/16] ASoC: amd: ps: add soundwire dma irq thread callback Add acp pci driver Soundwire DMA irq thread callaback for ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-7-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 8 ++++++++ sound/soc/amd/ps/pci-ps.c | 19 +------------------ sound/soc/amd/ps/ps-common.c | 25 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index a918a988e4d8..9a20846d30ff 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -222,6 +222,7 @@ struct acp63_dev_data; * @acp_init: ACP initialization * @acp_deinit: ACP de-initialization * @acp_get_config: function to read the acp pin configuration + * @acp_sdw_dma_irq_thread: ACP SoundWire DMA interrupt thread * acp_suspend: ACP system level suspend callback * acp_resume: ACP system level resume callback * acp_suspend_runtime: ACP runtime suspend callback @@ -231,6 +232,7 @@ struct acp_hw_ops { int (*acp_init)(void __iomem *acp_base, struct device *dev); int (*acp_deinit)(void __iomem *acp_base, struct device *dev); void (*acp_get_config)(struct pci_dev *pci, struct acp63_dev_data *acp_data); + void (*acp_sdw_dma_irq_thread)(struct acp63_dev_data *acp_data); int (*acp_suspend)(struct device *dev); int (*acp_resume)(struct device *dev); int (*acp_suspend_runtime)(struct device *dev); @@ -311,6 +313,12 @@ static inline void acp_hw_get_config(struct pci_dev *pci, struct acp63_dev_data ACP_HW_OPS(adata, acp_get_config)(pci, adata); } +static inline void acp_hw_sdw_dma_irq_thread(struct acp63_dev_data *adata) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_sdw_dma_irq_thread) + ACP_HW_OPS(adata, acp_sdw_dma_irq_thread)(adata); +} + static inline int acp_hw_suspend(struct device *dev) { struct acp63_dev_data *adata = dev_get_drvdata(dev); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 96399acf906c..5d9c230043a6 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -23,26 +23,9 @@ static irqreturn_t acp63_irq_thread(int irq, void *context) { - struct sdw_dma_dev_data *sdw_data; struct acp63_dev_data *adata = context; - u32 stream_id; - sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); - - for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) { - if (adata->acp63_sdw0_dma_intr_stat[stream_id]) { - if (sdw_data->acp63_sdw0_dma_stream[stream_id]) - snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]); - adata->acp63_sdw0_dma_intr_stat[stream_id] = 0; - } - } - for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) { - if (adata->acp63_sdw1_dma_intr_stat[stream_id]) { - if (sdw_data->acp63_sdw1_dma_stream[stream_id]) - snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]); - adata->acp63_sdw1_dma_intr_stat[stream_id] = 0; - } - } + acp_hw_sdw_dma_irq_thread(adata); return IRQ_HANDLED; } diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index 30e9e5fe034b..9098974b3608 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "acp63.h" @@ -211,11 +212,35 @@ static int __maybe_unused snd_acp63_resume(struct device *dev) return ret; } +static void acp63_sdw_dma_irq_thread(struct acp63_dev_data *adata) +{ + struct sdw_dma_dev_data *sdw_data; + u32 stream_id; + + sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); + + for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw0_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw0_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]); + adata->acp63_sdw0_dma_intr_stat[stream_id] = 0; + } + } + for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw1_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw1_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]); + adata->acp63_sdw1_dma_intr_stat[stream_id] = 0; + } + } +} + void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) { hw_ops->acp_init = acp63_init; hw_ops->acp_deinit = acp63_deinit; hw_ops->acp_get_config = acp63_get_config; + hw_ops->acp_sdw_dma_irq_thread = acp63_sdw_dma_irq_thread; hw_ops->acp_suspend = snd_acp63_suspend; hw_ops->acp_resume = snd_acp63_resume; hw_ops->acp_suspend_runtime = snd_acp63_suspend; -- 2.51.0 From 4516be370ced14c4fb454fd6cc016e47bffe109e Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:01 +0530 Subject: [PATCH 15/16] ASoC: amd: ps: refactor soundwire dma interrupt handling Move the Soundwire DMA interrupt handling to separate function. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-8-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/pci-ps.c | 96 ++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 5d9c230043a6..04b43b4128bc 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -21,6 +21,55 @@ #include "acp63.h" +static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 ext_intr_stat, + u32 ext_intr_stat1) +{ + u32 stream_id = 0; + u16 sdw_dma_irq_flag = 0; + u16 index; + + if (ext_intr_stat & ACP63_SDW_DMA_IRQ_MASK) { + for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) { + if (ext_intr_stat & BIT(index)) { + writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); + switch (index) { + case ACP_AUDIO0_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO0_TX; + break; + case ACP_AUDIO1_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO1_TX; + break; + case ACP_AUDIO2_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO2_TX; + break; + case ACP_AUDIO0_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO0_RX; + break; + case ACP_AUDIO1_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO1_RX; + break; + case ACP_AUDIO2_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO2_RX; + break; + } + adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; + sdw_dma_irq_flag = 1; + } + } + } + if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_RX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; + sdw_dma_irq_flag = 1; + } + if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_TX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; + sdw_dma_irq_flag = 1; + } + return sdw_dma_irq_flag; +} + static irqreturn_t acp63_irq_thread(int irq, void *context) { struct acp63_dev_data *adata = context; @@ -35,10 +84,8 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) struct pdm_dev_data *ps_pdm_data; struct amd_sdw_manager *amd_manager; u32 ext_intr_stat, ext_intr_stat1; - u32 stream_id = 0; u16 irq_flag = 0; u16 sdw_dma_irq_flag = 0; - u16 index; adata = dev_id; if (!adata) @@ -82,51 +129,8 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) snd_pcm_period_elapsed(ps_pdm_data->capture_stream); irq_flag = 1; } - if (ext_intr_stat & ACP63_SDW_DMA_IRQ_MASK) { - for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) { - if (ext_intr_stat & BIT(index)) { - writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); - switch (index) { - case ACP_AUDIO0_TX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO0_TX; - break; - case ACP_AUDIO1_TX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO1_TX; - break; - case ACP_AUDIO2_TX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO2_TX; - break; - case ACP_AUDIO0_RX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO0_RX; - break; - case ACP_AUDIO1_RX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO1_RX; - break; - case ACP_AUDIO2_RX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO2_RX; - break; - } - - adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; - sdw_dma_irq_flag = 1; - } - } - } - - if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { - writel(ACP63_P1_AUDIO1_RX_THRESHOLD, - adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; - sdw_dma_irq_flag = 1; - } - - if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { - writel(ACP63_P1_AUDIO1_TX_THRESHOLD, - adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; - sdw_dma_irq_flag = 1; - } + sdw_dma_irq_flag = check_and_handle_sdw_dma_irq(adata, ext_intr_stat, ext_intr_stat1); if (sdw_dma_irq_flag) return IRQ_WAKE_THREAD; -- 2.51.0 From fcb754602724fa2a1d0db72f13ddc3ef0306f911 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:02 +0530 Subject: [PATCH 16/16] ASoC: amd: ps: store acp revision id in SoundWire dma driver private data Store acp pci revision id in SoundWire dma driver private data structure. It will be used to distinguish platform specific code. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-9-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 1 + sound/soc/amd/ps/ps-sdw-dma.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 9a20846d30ff..098597d92bf9 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -183,6 +183,7 @@ struct pdm_dev_data { struct sdw_dma_dev_data { void __iomem *acp_base; struct mutex *acp_lock; /* used to protect acp common register access */ + u32 acp_rev; struct snd_pcm_substream *acp63_sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; struct snd_pcm_substream *acp63_sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; }; diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 878683619a05..b3c716371d15 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -474,6 +474,7 @@ static int acp63_sdw_platform_probe(struct platform_device *pdev) return -ENOMEM; sdw_data->acp_lock = &acp_data->acp_lock; + sdw_data->acp_rev = acp_data->acp_rev; dev_set_drvdata(&pdev->dev, sdw_data); status = devm_snd_soc_register_component(&pdev->dev, &acp63_sdw_component, -- 2.51.0