diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index f8eebb609a35..1209532bcd76 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 @@ -138,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 */ @@ -198,9 +201,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..ba6302dfc4ea 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,22 @@ 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) - dev->period = 1000000 * sink_get_min_free_space(sink) / - (sink_get_frame_bytes(sink) * sink_get_rate(sink)); - - comp_info(dev, "SRC DP period calculated as: %u", dev->period); + 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 + * + * calculate period using 64bit integer to avoid overflows + */ + 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; + dev->period *= LL_TIMER_PERIOD_US; + + 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 */