From 73366d9fcd92220b2a6044aa49cc51aba3715040 Mon Sep 17 00:00:00 2001 From: Marcin Szkudlinski Date: Wed, 26 Mar 2025 13:19:20 +0100 Subject: [PATCH 1/2] mod: align DP period down to LL cycle As DP EDF scheduler runs in LL cycles, DP period should be always calculated at granularity of LL cycle Fail preparation if a module calculated period shorter than 1LL cycle Signed-off-by: Marcin Szkudlinski --- src/audio/module_adapter/module_adapter.c | 19 ++++++++++++++++--- src/audio/src/src_ipc4.c | 22 +++++++++++++--------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index f8eebb609a35..4417c9291593 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -198,9 +199,21 @@ int module_adapter_prepare(struct comp_dev *dev) * but events and therefore don't have any deadline for processing * Second example is a module with variable data rate on output (like MPEG encoder) */ - if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP && !dev->period) { - module_adapter_calculate_dp_period(dev); - comp_info(dev, "DP Module period set to %u", dev->period); + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + /* calculate DP period if a module didn't */ + if (!dev->period) + module_adapter_calculate_dp_period(dev); + + if (dev->period < LL_TIMER_PERIOD_US) { + comp_err(dev, "DP Module period too short (%u us), must be at least 1LL cycle (%llu us)", + dev->period, LL_TIMER_PERIOD_US); + return -EINVAL; + } + + /* align down period to LL cycle time */ + dev->period /= LL_TIMER_PERIOD_US; + dev->period *= LL_TIMER_PERIOD_US; + comp_info(dev, "DP Module period set to %u us", dev->period); } #endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ diff --git a/src/audio/src/src_ipc4.c b/src/audio/src/src_ipc4.c index 5f50c17ec537..4d50563322b3 100644 --- a/src/audio/src/src_ipc4.c +++ b/src/audio/src/src_ipc4.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -99,17 +100,20 @@ int src_set_params(struct processing_module *mod, struct sof_sink *sink) src_params.frame_fmt = valid_fmt; ret = sink_set_params(sink, &src_params, true); - - /* if module is to be run as DP, calculate module period - * according to OBS size and data rate - * as SRC uses period value to calculate its internal buffers, - * it must be done here, right after setting sink parameters - */ - if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) + if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + /* if module is to be run as DP, calculate module period + * according to OBS size and data rate + * as SRC uses period value to calculate its internal buffers, + * it must be done here, right after setting sink parameters + */ dev->period = 1000000 * sink_get_min_free_space(sink) / - (sink_get_frame_bytes(sink) * sink_get_rate(sink)); + (sink_get_frame_bytes(sink) * sink_get_rate(sink)); + /* align down period to LL cycle time */ + dev->period /= LL_TIMER_PERIOD_US; + dev->period *= LL_TIMER_PERIOD_US; - comp_info(dev, "SRC DP period calculated as: %u", dev->period); + comp_info(dev, "SRC DP period calculated as: %u us", dev->period); + } component_set_nearest_period_frames(dev, src_params.rate); /* Update module stream_params */ From a82618b0bb20177e70e2c3e8325a47214747eee9 Mon Sep 17 00:00:00 2001 From: Marcin Szkudlinski Date: Fri, 28 Mar 2025 13:25:26 +0100 Subject: [PATCH 2/2] dp: use 64bit integers for period calculation for some huge bitrates there was an overflow in 32bit numbers in period calculations, i.e: dev->period = 1000000 * sink_get_min_free_space(sink) for 192000-32-7 format it was 5824000000, more than maxint32bit Signed-off-by: Marcin Szkudlinski --- src/audio/module_adapter/module_adapter.c | 6 ++++-- src/audio/src/src_ipc4.c | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 4417c9291593..1209532bcd76 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -139,8 +139,10 @@ static void module_adapter_calculate_dp_period(struct comp_dev *dev) unsigned int period = UINT32_MAX; for (int i = 0; i < mod->num_of_sinks; i++) { - /* calculate time required the module to provide OBS data portion - a period */ - unsigned int sink_period = 1000000 * sink_get_min_free_space(mod->sinks[i]) / + /* calculate time required the module to provide OBS data portion - a period + * use 64bit integers to avoid overflows + */ + unsigned int sink_period = 1000000ULL * sink_get_min_free_space(mod->sinks[i]) / (sink_get_frame_bytes(mod->sinks[i]) * sink_get_rate(mod->sinks[i])); /* note the minimal period for the module */ diff --git a/src/audio/src/src_ipc4.c b/src/audio/src/src_ipc4.c index 4d50563322b3..ba6302dfc4ea 100644 --- a/src/audio/src/src_ipc4.c +++ b/src/audio/src/src_ipc4.c @@ -105,8 +105,10 @@ int src_set_params(struct processing_module *mod, struct sof_sink *sink) * according to OBS size and data rate * as SRC uses period value to calculate its internal buffers, * it must be done here, right after setting sink parameters + * + * calculate period using 64bit integer to avoid overflows */ - dev->period = 1000000 * sink_get_min_free_space(sink) / + dev->period = 1000000ULL * sink_get_min_free_space(sink) / (sink_get_frame_bytes(sink) * sink_get_rate(sink)); /* align down period to LL cycle time */ dev->period /= LL_TIMER_PERIOD_US;