From 87bcb08710160bde5712ca0d24c505074b7dfafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 4 Apr 2025 11:03:32 +0200 Subject: ASoC: Intel: avs: Rename AVS_CHANNELS_MAX define MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is used for coefficient table in updown mixer module, which supports maximum of 8 channels. However it does not represent HW capability. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250404090337.3564117-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/messages.h | 4 ++-- sound/soc/intel/avs/path.c | 2 +- sound/soc/intel/avs/topology.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 2f243802ccc2..673e4577df14 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -697,7 +697,7 @@ enum avs_sample_type { AVS_SAMPLE_TYPE_FLOAT = 4, }; -#define AVS_CHANNELS_MAX 8 +#define AVS_COEFF_CHANNELS_MAX 8 #define AVS_ALL_CHANNELS_MASK UINT_MAX struct avs_audio_format { @@ -846,7 +846,7 @@ struct avs_updown_mixer_cfg { struct avs_modcfg_base base; u32 out_channel_config; u32 coefficients_select; - s32 coefficients[AVS_CHANNELS_MAX]; + s32 coefficients[AVS_COEFF_CHANNELS_MAX]; u32 channel_map; } __packed; static_assert(sizeof(struct avs_updown_mixer_cfg) == 84); diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index ef0c1d125d66..d5cce357b162 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -452,7 +452,7 @@ static int avs_updown_mix_create(struct avs_dev *adev, struct avs_path_module *m cfg.base.audio_fmt = *t->in_fmt; cfg.out_channel_config = t->cfg_ext->updown_mix.out_channel_config; cfg.coefficients_select = t->cfg_ext->updown_mix.coefficients_select; - for (i = 0; i < AVS_CHANNELS_MAX; i++) + for (i = 0; i < AVS_COEFF_CHANNELS_MAX; i++) cfg.coefficients[i] = t->cfg_ext->updown_mix.coefficients[i]; cfg.channel_map = t->cfg_ext->updown_mix.channel_map; diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h index 304880997717..f5601a4e3ec8 100644 --- a/sound/soc/intel/avs/topology.h +++ b/sound/soc/intel/avs/topology.h @@ -87,7 +87,7 @@ struct avs_tplg_modcfg_ext { struct { u32 out_channel_config; u32 coefficients_select; - s32 coefficients[AVS_CHANNELS_MAX]; + s32 coefficients[AVS_COEFF_CHANNELS_MAX]; u32 channel_map; } updown_mix; struct { -- cgit v1.2.3 From d360b713727db0093fe9a8cf475d1d536075c12f Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 4 Apr 2025 11:03:33 +0200 Subject: ASoC: Intel: avs: Allow for 16 channels configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add define representing maximum number of channels that are allowed by HDAudio standard and as such supported by HW - 16 channels. With that done, reflect the max in BE DAIs capabilities. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250404090337.3564117-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/messages.h | 1 + sound/soc/intel/avs/pcm.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 673e4577df14..e27c7587be9d 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -699,6 +699,7 @@ enum avs_sample_type { #define AVS_COEFF_CHANNELS_MAX 8 #define AVS_ALL_CHANNELS_MASK UINT_MAX +#define AVS_CHANNELS_MAX 16 struct avs_audio_format { u32 sampling_freq; diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index dac463390da1..7d57a5735157 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -1337,7 +1337,7 @@ static const struct snd_soc_dai_driver i2s_dai_template = { .ops = &avs_dai_nonhda_be_ops, .playback = { .channels_min = 1, - .channels_max = 8, + .channels_max = AVS_CHANNELS_MAX, .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_24000 | @@ -1350,7 +1350,7 @@ static const struct snd_soc_dai_driver i2s_dai_template = { }, .capture = { .channels_min = 1, - .channels_max = 8, + .channels_max = AVS_CHANNELS_MAX, .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_24000 | @@ -1431,7 +1431,7 @@ static const struct snd_soc_dai_driver hda_cpu_dai = { .ops = &avs_dai_hda_be_ops, .playback = { .channels_min = 1, - .channels_max = 8, + .channels_max = AVS_CHANNELS_MAX, .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, @@ -1441,7 +1441,7 @@ static const struct snd_soc_dai_driver hda_cpu_dai = { }, .capture = { .channels_min = 1, - .channels_max = 8, + .channels_max = AVS_CHANNELS_MAX, .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, -- cgit v1.2.3 From 7d859189de13f06fdc511761c745f3b302bed7b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 4 Apr 2025 11:03:34 +0200 Subject: ASoC: Intel: avs: Allow to specify custom configurations with i2s_test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change 'i2s_test' module option from enable-flag to string allowing to specify which SSP port and in what TDM configuration should be enabled. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250404090337.3564117-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/board_selection.c | 132 +++++++++++++++++----------------- 1 file changed, 67 insertions(+), 65 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 2d706edcbf92..30444b67dd91 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -17,10 +17,11 @@ #include #include #include "avs.h" +#include "utils.h" -static bool i2s_test; -module_param(i2s_test, bool, 0444); -MODULE_PARM_DESC(i2s_test, "Probe I2S test-board and skip all other I2S boards"); +static char *i2s_test; +module_param(i2s_test, charp, 0444); +MODULE_PARM_DESC(i2s_test, "Use I2S test-board instead of ACPI, i2s_test=ssp0tdm,ssp1tdm,... 0 to ignore port"); static const struct dmi_system_id kbl_dmi_table[] = { { @@ -324,52 +325,6 @@ static struct snd_soc_acpi_mach avs_mbl_i2s_machines[] = { {} }; -static struct snd_soc_acpi_mach avs_test_i2s_machines[] = { - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(0), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(1), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(2), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(3), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(4), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(5), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - /* no NULL terminator, as we depend on ARRAY SIZE due to .id == NULL */ -}; - struct avs_acpi_boards { int id; struct snd_soc_acpi_mach *machs; @@ -529,35 +484,82 @@ static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach return 0; } -static int avs_register_i2s_boards(struct avs_dev *adev) +static int avs_register_i2s_test_board(struct avs_dev *adev, int ssp_port, int tdm_slot) { - const struct avs_acpi_boards *boards; struct snd_soc_acpi_mach *mach; + int tdm_mask = BIT(tdm_slot); + unsigned long *tdm_cfg; + char *tplg_name; int ret; - if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP, -1, -1, -1)) { - dev_dbg(adev->dev, "no I2S endpoints present\n"); - return 0; + mach = devm_kzalloc(adev->dev, sizeof(*mach), GFP_KERNEL); + tdm_cfg = devm_kcalloc(adev->dev, ssp_port + 1, sizeof(unsigned long), GFP_KERNEL); + tplg_name = devm_kasprintf(adev->dev, GFP_KERNEL, AVS_STRING_FMT("i2s", "-test-tplg.bin", + ssp_port, tdm_slot)); + if (!mach || !tdm_cfg || !tplg_name) + return -ENOMEM; + + mach->drv_name = "avs_i2s_test"; + mach->mach_params.i2s_link_mask = AVS_SSP(ssp_port); + tdm_cfg[ssp_port] = tdm_mask; + mach->pdata = tdm_cfg; + mach->tplg_filename = tplg_name; + + ret = avs_register_i2s_board(adev, mach); + if (ret < 0) { + dev_warn(adev->dev, "register i2s %s failed: %d\n", mach->drv_name, ret); + return ret; } - if (i2s_test) { - int i, num_ssps; + return 0; +} - num_ssps = adev->hw_cfg.i2s_caps.ctrl_count; - /* constrain just in case FW says there can be more SSPs than possible */ - num_ssps = min_t(int, ARRAY_SIZE(avs_test_i2s_machines), num_ssps); +static int avs_register_i2s_test_boards(struct avs_dev *adev) +{ + int max_ssps = adev->hw_cfg.i2s_caps.ctrl_count; + int ssp_port, tdm_slot, ret; + unsigned long tdm_slots; + u32 *array, num_elems; - mach = avs_test_i2s_machines; + ret = parse_int_array(i2s_test, strlen(i2s_test), (int **)&array); + if (ret < 0) { + dev_err(adev->dev, "failed to parse i2s_test parameter\n"); + return ret; + } - for (i = 0; i < num_ssps; i++) { - ret = avs_register_i2s_board(adev, &mach[i]); - if (ret < 0) - dev_warn(adev->dev, "register i2s %s failed: %d\n", mach->drv_name, - ret); + num_elems = *array; + if (num_elems > max_ssps) { + dev_err(adev->dev, "board supports only %d SSP, %d specified\n", + max_ssps, num_elems); + return -EINVAL; + } + + for (ssp_port = 0; ssp_port < num_elems; ssp_port++) { + tdm_slots = array[1 + ssp_port]; + for_each_set_bit(tdm_slot, &tdm_slots, 16) { + ret = avs_register_i2s_test_board(adev, ssp_port, tdm_slot); + if (ret) + return ret; } + } + + return 0; +} + +static int avs_register_i2s_boards(struct avs_dev *adev) +{ + const struct avs_acpi_boards *boards; + struct snd_soc_acpi_mach *mach; + int ret; + + if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP, -1, -1, -1)) { + dev_dbg(adev->dev, "no I2S endpoints present\n"); return 0; } + if (i2s_test) + return avs_register_i2s_test_boards(adev); + boards = avs_get_i2s_boards(adev); if (!boards) { dev_dbg(adev->dev, "no I2S endpoints supported\n"); -- cgit v1.2.3 From 79138dbff53ab0e9891ebdfce8d7b298c3783cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 4 Apr 2025 11:03:35 +0200 Subject: ASoC: Intel: avs: Assign unique ID to platform devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When creating machine boards there are two types, per endpoint or compound board. For compound board we can just use I2S mask as its ID, however, per endpoint can also be separated per TDM, which causes problem because two boards would have same I2S mask. Shift it and add the value of TDM to generate a unique ID. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250404090337.3564117-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/board_selection.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 30444b67dd91..286d94df5f46 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -448,6 +448,7 @@ static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach int num_ssps; char *name; int ret; + int uid; num_ssps = adev->hw_cfg.i2s_caps.ctrl_count; if (fls(mach->mach_params.i2s_link_mask) > num_ssps) { @@ -457,8 +458,11 @@ static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach return -ENODEV; } - name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%d-platform", mach->drv_name, - mach->mach_params.i2s_link_mask); + uid = mach->mach_params.i2s_link_mask; + if (avs_mach_singular_ssp(mach)) + uid = (uid << AVS_CHANNELS_MAX) + avs_mach_ssp_tdm(mach, avs_mach_ssp_port(mach)); + + name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%d-platform", mach->drv_name, uid); if (!name) return -ENOMEM; @@ -468,7 +472,7 @@ static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach mach->mach_params.platform = name; - board = platform_device_register_data(NULL, mach->drv_name, mach->mach_params.i2s_link_mask, + board = platform_device_register_data(NULL, mach->drv_name, uid, (const void *)mach, sizeof(*mach)); if (IS_ERR(board)) { dev_err(adev->dev, "ssp board register failed\n"); -- cgit v1.2.3 From 6a68cbe09e9a7dc9f53857510bee1bc34bdbbfd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 4 Apr 2025 11:03:36 +0200 Subject: ASoC: Intel: avs: Iterate over correct number of TDMs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When handling TDMs, don't iterate over number of SSP ports, but over possible number of TDMs. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250404090337.3564117-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 7d57a5735157..9dd5215b2c72 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -1406,7 +1406,7 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l goto plat_register; for_each_set_bit(i, &port_mask, ssp_count) { - for_each_set_bit(j, &tdms[i], ssp_count) { + for_each_set_bit(j, &tdms[i], AVS_CHANNELS_MAX) { memcpy(dai, &i2s_dai_template, sizeof(*dai)); dai->name = -- cgit v1.2.3 From 8d18e67abbdf380cd1cfd2c313aac625092d7777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 4 Apr 2025 11:03:37 +0200 Subject: ASoC: Intel: avs: Support 16 TDMs in dynamic assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When assigning new widget name there needs to be enough place in buffer to assign name. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250404090337.3564117-9-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 3c222c352701..f2e4ad8b8e14 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -1668,8 +1668,8 @@ static int avs_widget_load(struct snd_soc_component *comp, int index, /* See parse_link_formatted_string() for dynamic naming when(s). */ if (avs_mach_singular_tdm(mach, ssp_port)) { - /* size is based on possible %d -> SSP:TDM, where SSP and TDM < 10 + '\0' */ - size_t size = strlen(dw->name) + 2; + /* size is based on possible %d -> SSP:TDM, where SSP and TDM < 16 + '\0' */ + size_t size = strlen(dw->name) + 3; char *buf; tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); -- cgit v1.2.3