From 6c6a1867278a3f47b1e21e8af6a407d73c83dcab Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 23 Nov 2023 16:56:30 +0200 Subject: [PATCH 01/48] audio: pipeline: do not propagate pipeline triggers for IPC4 One major difference in IPC4 versus IPC3 is that each pipeline will get a separate SET_PIPELINE_STATE command. This is in stark contrast to IPC3 where host sends STREAM_TRIG_START and firmware is expected to propagate the state change to all connected pipelines in the graph. Change the code such that when pipeline component trigger is executed in IPC4 build, propagation is stopped whenever we reach another pipeline. This prevents bugs stemming from IPC3 related logic to propagate pipeline triggers, interfering with IPC4 usages like in bug 8481. To avoid false -ENODATA errors, drop IPC4 support for this capability. The check added in commit b154132b46ea ("ipc4: check pipeline priority for error report") covers most cases, but this relies on host to send the SET_PIPELINE_STATE calls in particular order. This unfortunately is not a mandatory order to follow, so logic to check upstream pipeline status to conclude downstream is in permanent -ENODATA state, is not as solid as it is for IPC3. As this may lead to hard to debug errors (e.g. when changing pipeline priorities in topologies which again affects the order of the SET_PIPELINE_STATE), better to simply disable this feature for IPC4. Link: https://github.com/thesofproject/sof/issues/8481 Signed-off-by: Kai Vehmanen --- src/audio/pipeline/pipeline-stream.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/audio/pipeline/pipeline-stream.c b/src/audio/pipeline/pipeline-stream.c index d4e24d36451e..af696810d5c5 100644 --- a/src/audio/pipeline/pipeline-stream.c +++ b/src/audio/pipeline/pipeline-stream.c @@ -47,6 +47,17 @@ pipeline_should_report_enodata_on_trigger(struct comp_dev *rsrc, struct pipeline_data *ppl_data = ctx->comp_data; struct comp_dev *pipe_source = ppl_data->start->pipeline->source_comp; + /* In IPC3, FW propagates triggers to connected pipelines, so + * it can have determistic logic to conclude no data is + * available. + * In IPC4, host controls state of each pipeline separately, + * so FW cannot reliably detect case of no data based on + * observing state of src->pipeline here. + */ +#if CONFIG_IPC_MAJOR_4 + return false; +#endif + /* only applies to capture pipelines */ if (dir != SOF_IPC_STREAM_CAPTURE) return false; @@ -388,8 +399,13 @@ static int pipeline_comp_trigger(struct comp_dev *current, /* trigger should propagate to the connected pipelines, * which need to be scheduled together + * + * IPC4 has a SET_PIPELINE_STATE for each pipeline, so FW + * should not propagate triggers on its own. + * IPC3 has commands only for graph edges, so propagation is + * needed in many cases. */ - if (!is_single_ppl && !is_same_sched) { + if (!is_single_ppl && (!is_same_sched || IS_ENABLED(CONFIG_IPC_MAJOR_4))) { pipe_dbg(current->pipeline, "pipeline_comp_trigger(), current is from another pipeline"); From 05bffd7e306e5febba1866724e2f7f28c56cd471 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 20 Nov 2023 20:59:02 +0200 Subject: [PATCH 02/48] ipc4: handler: maintain IPC set_pipeline_state order Fix a side-effect of commit 068f14381026 ("ipc4: handler: Use separate loops for pipeline state phases") where the order of pipeline triggers was changed when the trigger handling was delayed to the pipeline thread. If host asked for pipelines to be triggered in order 2, 1, 0, the actual trigger order might end up as 0, 1, 2 based on how LL scheduler runs the pipeline tasks (0 is run first). Fix the issue by adding a blocking wait to the IPC thread between each delayed trigger. Link: https://github.com/thesofproject/sof/issues/8481 Signed-off-by: Kai Vehmanen --- src/ipc/ipc4/handler.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index 62236643201d..14978252a610 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -630,6 +630,17 @@ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4) ipc_compound_pre_start(state.primary.r.type); ret = ipc4_pipeline_trigger(ppl_icd, cmd, &delayed); ipc_compound_post_start(state.primary.r.type, ret, delayed); + if (delayed) { + /* To maintain pipeline order for triggers, we must + * do a blocking wait until trigger is processed. + * This will add a max delay of 'ppl_count' LL ticks + * to process the full trigger list. + */ + if (ipc_wait_for_compound_msg() != 0) { + ipc_cmd_err(&ipc_tr, "ipc4: fail with delayed trigger"); + return IPC4_FAILURE; + } + } } if (ret != 0) From f1ee910fc220838666a6a20da8fa70ea41efd78c Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Thu, 23 Nov 2023 11:35:15 +0800 Subject: [PATCH 03/48] west.yml: update Zephyr to efc32081893d Update Zephyr to bring in following Zephyr commit: efc32081893d soc: intel_adsp: cavs: mask idc interrupt before halting cpu Link: https://github.com/thesofproject/sof/issues/8492 Signed-off-by: Rander Wang --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 526804cbf010..39e24a770c7a 100644 --- a/west.yml +++ b/west.yml @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: 063ce9caf54fa656f02ae48f3c9d537659a10dec + revision: efc32081893dd607dfc51938ef93787872008fe2 remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision From f4d043724d77741d17be5a6f5cf390ff66d485f1 Mon Sep 17 00:00:00 2001 From: Andrula Song Date: Fri, 17 Nov 2023 16:22:01 +0800 Subject: [PATCH 04/48] Audio: Move components related config to subfolder Create a Kconfig for each module and include them from src/audio/Konfig. Signed-off-by: Andrula Song --- src/audio/Kconfig | 446 ++------------------------------ src/audio/aria/Kconfig | 12 + src/audio/asrc/Kconfig | 134 ++++++++++ src/audio/copier/Kconfig | 28 ++ src/audio/crossover/Kconfig | 11 + src/audio/dcblock/Kconfig | 8 + src/audio/drc/Kconfig | 23 ++ src/audio/eq_fir/Kconfig | 15 ++ src/audio/eq_iir/Kconfig | 10 + src/audio/igo_nr/Kconfig | 20 ++ src/audio/mfcc/Kconfig | 24 ++ src/audio/mixer/Kconfig | 7 + src/audio/mixin_mixout/Kconfig | 12 + src/audio/multiband_drc/Kconfig | 12 + src/audio/mux/Kconfig | 9 + src/audio/rtnr/Kconfig | 24 ++ src/audio/selector/Kconfig | 7 + src/audio/smart_amp/Kconfig | 13 + src/audio/src/Kconfig | 68 +++++ src/audio/tdfb/Kconfig | 20 ++ src/audio/up_down_mixer/Kconfig | 15 ++ 21 files changed, 491 insertions(+), 427 deletions(-) create mode 100644 src/audio/aria/Kconfig create mode 100644 src/audio/asrc/Kconfig create mode 100644 src/audio/copier/Kconfig create mode 100644 src/audio/crossover/Kconfig create mode 100644 src/audio/dcblock/Kconfig create mode 100644 src/audio/drc/Kconfig create mode 100644 src/audio/eq_fir/Kconfig create mode 100644 src/audio/eq_iir/Kconfig create mode 100644 src/audio/igo_nr/Kconfig create mode 100644 src/audio/mfcc/Kconfig create mode 100644 src/audio/mixer/Kconfig create mode 100644 src/audio/mixin_mixout/Kconfig create mode 100644 src/audio/multiband_drc/Kconfig create mode 100644 src/audio/mux/Kconfig create mode 100644 src/audio/rtnr/Kconfig create mode 100644 src/audio/selector/Kconfig create mode 100644 src/audio/src/Kconfig create mode 100644 src/audio/tdfb/Kconfig create mode 100644 src/audio/up_down_mixer/Kconfig diff --git a/src/audio/Kconfig b/src/audio/Kconfig index 1ea03b65e603..0c4944926ac2 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -3,6 +3,7 @@ menu "Audio components" rsource "volume/Kconfig" +rsource "aria/Kconfig" config COMP_BASEFW_IPC4 bool "BASEFW component" @@ -11,18 +12,13 @@ config COMP_BASEFW_IPC4 help Select for BASEFW component -config COMP_COPIER - bool "COPIER component" - default y - depends on IPC_MAJOR_4 - help - Select for COPIER component +rsource "copier/Kconfig" config HOST_DMA_RELOAD_DELAY_ENABLE bool "Delay reloading DMA for host interfaces" default y help - When deep buffers are used the firmware doesn't need to have the + When deep buffers are used the firmware does not need to have the buffer refilled every millisecond. Select this option to enable longer delays and to allow the memory controller to enter power saving modes. @@ -44,26 +40,6 @@ config HOST_DMA_STREAM_SYNCHRONIZATION for each group, different than the default one determined by the system tick frequency. This feature will allow host lower power consumption in scenarios with deep buffering. -config COMP_DAI - bool "DAI component" - default y - help - Select for DAI component - -config COMP_DAI_STOP_TRIGGER_ORDER_REVERSE - bool "Reverse the ordering of DMA and DAI triggers during STOP/PAUSE" - help - Select if the ordering of DMA and DAI triggers during stop/pause should be reversed. - The normal order during stop/pause is to stop DAI before stopping DMA. This option will - allow reversing the order to do DMA stop before stopping DAI. - -config COMP_DAI_GROUP - bool "DAI Grouping support" - default y - help - Select for grouping physical DAIs into a logical DAI that can be - triggered atomically to synchronise stream start and stop operations. - config COMP_CHAIN_DMA bool "Chain DMA component" default n @@ -87,30 +63,7 @@ config IPC4_GATEWAY host and DSP without using DMA: via memory window (audio payload) and IPC4 messages (set/get/flush commands). -config COMP_ARIA - bool "ARIA component" - default n - depends on IPC_MAJOR_4 - help - Select for Automatic Regressive Input Amplifier Module component - ARIA applies variable gain into incoming signal. - Applied gain is in range <1, 2 power attenuation> - Currently ARIA introduces gain transition and algorithmic - latency equal to 1 ms. - -config COMP_UP_DOWN_MIXER - bool "UP_DOWN_MIXER component" - default n - depends on IPC_MAJOR_4 - help - Select for Up Down Mixer component Conversions supported: - Up/Downmixing for stereo output: - 1, 2, 2.1, 3.0, 3.1, Quatro, 4.0, 5.0, 5.1, 7.1 -> 2 - Upmixing for multichannel output: - 1, 2 -> 5.1 - 2 -> 7.1 - Downmixing for mono output: - 4.0, Quatro, 3.1, 2 -> 1 +rsource "up_down_mixer/Kconfig" config COMP_BLOB bool "Large IPC data as compound message blobs" @@ -120,23 +73,7 @@ config COMP_BLOB multiple IPC messages. Not all components or modules need this. If unsure, say yes. -config COMP_SRC - bool "SRC component" - default y - help - Select for SRC component - -config COMP_SRC_LITE - bool "SRC_LITE component" - default y - help - Select for SRC_LITE component - which only supports a subset of conversions - supported by the SRC module: - 48 -> 16kHz - 44.1 -> 16 kHz - 32 -> 16 kHz - 44.1 -> 48 +rsource "src/Kconfig" config COMP_STUBS bool "Build all selected third-party (3P) components with stubs" @@ -145,78 +82,9 @@ config COMP_STUBS Select to force all 3P blocks to link against stubs rather than their libraries. This should only be used in testing environments like fuzzers or CI. -if COMP_SRC - -choice - prompt "SRC coefficient set" - default COMP_SRC_STD - -config COMP_SRC_STD - bool "Full conversions support and high quality" - help - This coefficients set supports a large number of conversions - with 8 - 192 kHz input and 8 - 48 kHz output. The coefficients - are 32 bits for high conversion quality. The coefficients - storage consume 79 kB. The runtime needs 8 kB. Use this if there - is critical quality usage for SRC like music via headphones and - need high sample rates. - -config COMP_SRC_SMALL - bool "Smaller conversions support and high quality" - help - This coefficients set supports a small number of conversions - with 8 - 48 kHz input and output. The coefficients are 32 bits - for high conversion quality. The coefficients storage consumes - 30 kB RAM. Runtime needs 4 kB. Use this if there is critical - quality usage for SRC like music via headphones. - -config COMP_SRC_TINY - bool "Reduced conversions support and reduced quality" - help - This coefficients set supports a minimum number of conversions - with 8 - 48 kHz input and output. The coefficients are 16 bits - that restricts the possible stop-attenuation and could cause - some audible aliasing. The bandwidth of the filters is restricted - so the full 20 kHz band is not met even if sample rate would - allow. The coefficients storage consumes 5 kB RAM. The runtime - needs 6 kB. Use this to save RAM for other applications when SRC - has no critical usage or when only need with lower quality - endpoint like miniature speakers. - -config COMP_SRC_IPC4_FULL_MATRIX - bool "Full IPC4 conversions matrix support and high quality" - help - This coefficients set supports a large number of conversions - with 8 - 192 kHz input 8 - 192 kHz output. The 32 bits coefficients - storate consumes 241 kB. The runtime needs 9 kB. Use this to - make the full conversions set available for IPC4 build. - -endchoice - -endif # SRC - -config COMP_FIR - bool "FIR component" - select MATH_FIR - select COMP_BLOB - depends on COMP_MODULE_ADAPTER - default y - help - Select for FIR component. FIR performance can differ between DSP - ISA and compiler used. FIR will perform best when MAC instructions - are available in ISA and are used by the compiler. i.e. xt-xcc on - xtensa will generate MAC instructions but GCC on xtensa won't. - Filter tap count can be severely restricted to reduce FIR cycles - and FIR performance for DSP/compilers with no MAC support +rsource "eq_fir/Kconfig" -config COMP_IIR - bool "IIR component" - select COMP_BLOB - default y - depends on COMP_MODULE_ADAPTER - select MATH_IIR_DF1 - help - Select for IIR component +rsource "eq_iir/Kconfig" config COMP_TONE bool "Tone component" @@ -226,19 +94,9 @@ config COMP_TONE Select for Tone component. Warning: This component is deprecated and will be removed from SOF v2.8. -config COMP_MIXER - bool "Mixer component" - default y - help - Select for Mixer component +rsource "mixer/Kconfig" -config COMP_MUX - bool "MUX component" - select COMP_BLOB - depends on COMP_MODULE_ADAPTER - default y - help - Select for MUX component +rsource "mux/Kconfig" config COMP_KPB bool "KPB component" @@ -258,228 +116,21 @@ endif # COMP_KPB rsource "google/Kconfig" -config COMP_SEL - bool "Channel selector component" - default y - help - Select for SEL component +rsource "selector/Kconfig" -config COMP_CROSSOVER - bool "Crossover Filter component" - select COMP_BLOB - select MATH_IIR_DF2T - default n - help - Select for Crossover Filter component. A crossover can be used to - split a signal into two or more frequency ranges, so that the outputs - can be sent to drivers that are designed for those ranges. +rsource "crossover/Kconfig" -config COMP_DRC - bool "Dynamic Range Compressor component" - select CORDIC_FIXED - select NUMBERS_NORM - select MATH_DECIBELS - select COMP_BLOB - default n - help - Select for Dynamic Range Compressor (DRC) component. A DRC can be used - to reduce the volume of loud sounds and amplify silent sounds thus - compressing an audio signal's dynamic range. +rsource "drc/Kconfig" -config DRC_MAX_PRE_DELAY_FRAMES - depends on COMP_DRC - int "DRC max number of pre-delay frames" - default 512 - help - Determines the length of pre-delay frame buffers which are allocated - runtime on DRC setup. It requires to be a 2^N number. 512 is - suggested by inference to avoid memory waste and provide reasonable - length for pre-delay frames. +rsource "multiband_drc/Kconfig" -config COMP_MULTIBAND_DRC - depends on COMP_IIR && COMP_CROSSOVER && COMP_DRC - bool "Multiband Dynamic Range Compressor component" - select CORDIC_FIXED - select COMP_BLOB - default n - help - Select for Multiband Dynamic Range Compressor (DRC) component. It - consists of Emphasis Equalizer, n-way Crossover Filter, per-band DRC, - and Deemphasis Equalizer. - -config COMP_DCBLOCK - bool "DC Blocking Filter component" - default y - help - Select for DC Blocking Filter component. This component filters out - the DC offset which often originates from a microphone's output. - -config COMP_SMART_AMP - bool "Smart Amplifier component" - select COMP_BLOB - default n - help - Select for Smart Amp component. This component protect the speaker - from overheating and excursion violation. This consists of two parts - which are feedforward processing block running on playback thread - and feedback processing block running on capture thread with amp - current and voltage feedback. The internal design of this component - depends on the applied Amplifier HW solution, which should be provided - by the solution supplier respectively. +rsource "dcblock/Kconfig" rsource "smart_amp/Kconfig" -config COMP_ASRC - bool "ASRC component" - default y - help - Select for Asynchronous sample rate conversion (ASRC) - component. The ASRC has the capabilities of (synchronous) - SRC but can in addition track a slave DAI that is not in - sync with firmware timer. The ASRC can be setup for - synchronous operation without DAI tracking via topology - though it has a bit higher computational load than SRC. The - RAM footprint of ASRC is smaller than SRC because it does - not have pre-computed filter coefficients for every - conversion fraction that SRC does. - -if COMP_ASRC - -choice - prompt "ASRC down sampling conversions set" - default COMP_ASRC_DOWNSAMPLING_FULL - -config COMP_ASRC_DOWNSAMPLING_FULL - bool "Full downsampling conversions support" - select ASRC_SUPPORT_CONVERSION_24000_TO_08000 - select ASRC_SUPPORT_CONVERSION_24000_TO_16000 - select ASRC_SUPPORT_CONVERSION_48000_TO_08000 - select ASRC_SUPPORT_CONVERSION_48000_TO_11025 - select ASRC_SUPPORT_CONVERSION_48000_TO_12000 - select ASRC_SUPPORT_CONVERSION_48000_TO_16000 - select ASRC_SUPPORT_CONVERSION_48000_TO_22050 - select ASRC_SUPPORT_CONVERSION_48000_TO_24000 - select ASRC_SUPPORT_CONVERSION_48000_TO_32000 - select ASRC_SUPPORT_CONVERSION_48000_TO_44100 - help - This option enables all supported downsampling conversions - for the asynchronous sample rate conversion. All the - upsampling conversions use the same filter always enabled - coefficients set so there is no configuration options for - them. The enabled conversions consume about 18 kB of memory. - -config COMP_ASRC_DOWNSAMPLING_CUSTOM - bool "Custom downsampling conversions support" - help - This option used to manually select each downsampling ratio. - In order to optimize the text code size of the sample rate - converter, non-required conversion ratios can be - deactivated. Disregarding these settings, the sample rate - converter always supports all conversion ratios with fs_in - less or equal to fs_out. Therefore, it is possible to - deactivate all conversion ratios listed below, if we only - need an (asynchronous) 1:1 sample rate conversion, e.g, from - 16 kHz to 16 kHz. This option allows to trim down the coefficient - memory for conversion down from default 18 kB. Each conversion - needs about 2 kB. - -endchoice - -menu "Supported downsampling conversions" - visible if COMP_ASRC_DOWNSAMPLING_CUSTOM - -config ASRC_SUPPORT_CONVERSION_24000_TO_08000 - bool "Downsample 24 kHz to 8 kHz" - default n - help - This option enables downsampling from 24 kHz to 8 kHz into - the build. The consumption of memory is 2.1 kB. - -config ASRC_SUPPORT_CONVERSION_24000_TO_16000 - bool "Downsample 24 kHz to 16 kHz" - default n - help - This option enables downsampling from 24 kHz to 16 kHz into - the build. The consumption of memory is 1.9 kB. - -config ASRC_SUPPORT_CONVERSION_48000_TO_08000 - bool "Downsample 48 kHz to 8 kHz" - default n - help - This option enables downsampling from 48 kHz to 8 kHz into - the build. The consumption of memory is 2.1 kB. - -config ASRC_SUPPORT_CONVERSION_48000_TO_11025 - bool "Downsample 48 kHz to 11.025 kHz" - default n - help - This option enables downsampling from 48 kHz to 11.025 kHz - into the build. The consumption of memory is 1.5 kB. - -config ASRC_SUPPORT_CONVERSION_48000_TO_12000 - bool "Downsample 48 kHz to 12 kHz" - default n - help - This option enables downsampling from 48 kHz to 12 kHz into - the build. The consumption of memory is 1.5 kB. - -config ASRC_SUPPORT_CONVERSION_48000_TO_16000 - bool "Downsample 48 kHz to 16 kHz" - default n - help - This option enables downsampling from 48 kHz to 16 kHz into - the build. The consumption of memory is 1.9 kB. - -config ASRC_SUPPORT_CONVERSION_48000_TO_22050 - bool "Downsample 48 kHz to 22.05 kHz" - default n - help - This option enables downsampling from 48 kHz to 22.05 kHz into - the build. The consumption of memory is 1.6 kB. +rsource "asrc/Kconfig" -config ASRC_SUPPORT_CONVERSION_48000_TO_24000 - bool "Downsample 48 kHz to 24 kHz" - default n - help - This option enables downsampling from 48 kHz to 24 kHz into - the build. The consumption of memory is 1.6 kB. - -config ASRC_SUPPORT_CONVERSION_48000_TO_32000 - bool "Downsample 48 kHz to 32 kHz" - default n - help - This option enables downsampling from 48 kHz to 32 kHz into - the build. The consumption of memory is 1.9 kB. - -config ASRC_SUPPORT_CONVERSION_48000_TO_44100 - bool "Downsample 48 kHz to 44.1 kHz" - default n - help - This option enables downsampling from 48 kHz to 44.1 kHz - into the build. The consumption of memory is 1.8 kB. - -endmenu # "Downsampling ratios" - -endif # COMP_ASRC - -config COMP_TDFB - bool "TDFB component" - depends on COMP_MODULE_ADAPTER - select MATH_FIR - select MATH_IIR_DF1 - select SQRT_FIXED - select CORDIC_FIXED - select COMP_BLOB - default y - help - Select for time domain fixed beamformer (TDFB) component. The - beamformer component enhances microphone capture by spatial - suppression of noise and improvement of signal-to-noise ratio of - capture from beam direction. The component is essentially a generic - single rate FIR filter bank that performs microphone array - directivity enhancement when programmed with suitable configuration - for channels selection, channel filter coefficients, and output - streams mixing. +rsource "tdfb/Kconfig" config COMP_MODULE_ADAPTER bool "Module adapter" @@ -494,70 +145,11 @@ config COMP_MODULE_ADAPTER rsource "module_adapter/Kconfig" -config COMP_IGO_NR - bool "IGO NR component" - select COMP_BLOB - select COMP_IGO_NR_STUB if COMP_STUBS - default n - help - This option enables Intelligo non-speech noise reduction. The feature links to a proprietary - binary libigonr.a that currently is supported on different Xtensa DSP platforms. Please email - info@intelli-go.com for any questions about the binary. +rsource "igo_nr/Kconfig" -config COMP_IGO_NR_STUB - bool "IGO NR component" - select COMP_BLOB - depends on COMP_IGO_NR - default n - help - This option builds the IGO adapter with a stub library, it should only be used for - testing or CI purposes. +rsource "rtnr/Kconfig" -config COMP_RTNR - bool "RTNR component" - select COMP_BLOB - select COMP_RTNR_STUB if COMP_STUBS - default n - help - Select for Realtek noise reduction/suppression(NR/NS) component. - Noise Suppression technology reduces stationary and transient noises in - single-channel speech signals, which increases the signal-to-noise ratio, - improves speech intelligibility and reduces listening fatigue. It estimates - ambient noise and signal levels and then passes or attenuates the signals - according to improve signal-to-noise ratios. The feature links to a - proprietary binary libSOF_RTK_MA_API.a, libSuite_rename.a, libNet.a and libPreset.a. - Please contact antz0525@realtek.com for any question about the binary. - -config COMP_RTNR_STUB - bool "RTNR component stub" - select COMP_BLOB - depends on COMP_RTNR - default n - help - Stub out the RTNR library for testing and CI purposes. - -config COMP_MFCC - bool "MFCC component" - depends on COMP_MODULE_ADAPTER - select CORDIC_FIXED - select MATH_16BIT_MEL_FILTERBANK - select MATH_AUDITORY - select MATH_DCT - select MATH_DECIBELS - select MATH_FFT - select MATH_MATRIX - select MATH_WINDOW - select NATURAL_LOGARITHM_FIXED - select NUMBERS_NORM - select SQRT_FIXED - default y - help - This option enables build of a Mel-frequency cepstral coefficients - (MFCC) audio features extractor component. It converts the input - audio stream into encoded audio data for cepstral coefficients. - The characteristic of the audio features are defined in the binary - control blob. Directory tools/tune/mfcc contains a tool to create - the configurations. +rsource "mfcc/Kconfig" endmenu # "Audio components" diff --git a/src/audio/aria/Kconfig b/src/audio/aria/Kconfig new file mode 100644 index 000000000000..ba1b1bfda9fe --- /dev/null +++ b/src/audio/aria/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_ARIA + bool "ARIA component" + default n + depends on IPC_MAJOR_4 + help + Select for Automatic Regressive Input Amplifier Module component + ARIA applies variable gain into incoming signal. + Applied gain is in range <1, 2 power attenuation> + Currently ARIA introduces gain transition and algorithmic + latency equal to 1 ms. diff --git a/src/audio/asrc/Kconfig b/src/audio/asrc/Kconfig new file mode 100644 index 000000000000..9e121ada2d1f --- /dev/null +++ b/src/audio/asrc/Kconfig @@ -0,0 +1,134 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_ASRC + bool "ASRC component" + default y + help + Select for Asynchronous sample rate conversion (ASRC) + component. The ASRC has the capabilities of (synchronous) + SRC but can in addition track a slave DAI that is not in + sync with firmware timer. The ASRC can be setup for + synchronous operation without DAI tracking via topology + though it has a bit higher computational load than SRC. The + RAM footprint of ASRC is smaller than SRC because it does + not have pre-computed filter coefficients for every + conversion fraction that SRC does. + +if COMP_ASRC + +choice + prompt "ASRC down sampling conversions set" + default COMP_ASRC_DOWNSAMPLING_FULL + +config COMP_ASRC_DOWNSAMPLING_FULL + bool "Full downsampling conversions support" + select ASRC_SUPPORT_CONVERSION_24000_TO_08000 + select ASRC_SUPPORT_CONVERSION_24000_TO_16000 + select ASRC_SUPPORT_CONVERSION_48000_TO_08000 + select ASRC_SUPPORT_CONVERSION_48000_TO_11025 + select ASRC_SUPPORT_CONVERSION_48000_TO_12000 + select ASRC_SUPPORT_CONVERSION_48000_TO_16000 + select ASRC_SUPPORT_CONVERSION_48000_TO_22050 + select ASRC_SUPPORT_CONVERSION_48000_TO_24000 + select ASRC_SUPPORT_CONVERSION_48000_TO_32000 + select ASRC_SUPPORT_CONVERSION_48000_TO_44100 + help + This option enables all supported downsampling conversions + for the asynchronous sample rate conversion. All the + upsampling conversions use the same filter always enabled + coefficients set so there is no configuration options for + them. The enabled conversions consume about 18 kB of memory. + +config COMP_ASRC_DOWNSAMPLING_CUSTOM + bool "Custom downsampling conversions support" + help + This option used to manually select each downsampling ratio. + In order to optimize the text code size of the sample rate + converter, non-required conversion ratios can be + deactivated. Disregarding these settings, the sample rate + converter always supports all conversion ratios with fs_in + less or equal to fs_out. Therefore, it is possible to + deactivate all conversion ratios listed below, if we only + need an (asynchronous) 1:1 sample rate conversion, e.g, from + 16 kHz to 16 kHz. This option allows to trim down the coefficient + memory for conversion down from default 18 kB. Each conversion + needs about 2 kB. + +endchoice + +menu "Supported downsampling conversions" + visible if COMP_ASRC_DOWNSAMPLING_CUSTOM + +config ASRC_SUPPORT_CONVERSION_24000_TO_08000 + bool "Downsample 24 kHz to 8 kHz" + default n + help + This option enables downsampling from 24 kHz to 8 kHz into + the build. The consumption of memory is 2.1 kB. + +config ASRC_SUPPORT_CONVERSION_24000_TO_16000 + bool "Downsample 24 kHz to 16 kHz" + default n + help + This option enables downsampling from 24 kHz to 16 kHz into + the build. The consumption of memory is 1.9 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_08000 + bool "Downsample 48 kHz to 8 kHz" + default n + help + This option enables downsampling from 48 kHz to 8 kHz into + the build. The consumption of memory is 2.1 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_11025 + bool "Downsample 48 kHz to 11.025 kHz" + default n + help + This option enables downsampling from 48 kHz to 11.025 kHz + into the build. The consumption of memory is 1.5 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_12000 + bool "Downsample 48 kHz to 12 kHz" + default n + help + This option enables downsampling from 48 kHz to 12 kHz into + the build. The consumption of memory is 1.5 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_16000 + bool "Downsample 48 kHz to 16 kHz" + default n + help + This option enables downsampling from 48 kHz to 16 kHz into + the build. The consumption of memory is 1.9 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_22050 + bool "Downsample 48 kHz to 22.05 kHz" + default n + help + This option enables downsampling from 48 kHz to 22.05 kHz into + the build. The consumption of memory is 1.6 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_24000 + bool "Downsample 48 kHz to 24 kHz" + default n + help + This option enables downsampling from 48 kHz to 24 kHz into + the build. The consumption of memory is 1.6 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_32000 + bool "Downsample 48 kHz to 32 kHz" + default n + help + This option enables downsampling from 48 kHz to 32 kHz into + the build. The consumption of memory is 1.9 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_44100 + bool "Downsample 48 kHz to 44.1 kHz" + default n + help + This option enables downsampling from 48 kHz to 44.1 kHz + into the build. The consumption of memory is 1.8 kB. + +endmenu # "Downsampling ratios" + +endif # COMP_ASRC diff --git a/src/audio/copier/Kconfig b/src/audio/copier/Kconfig new file mode 100644 index 000000000000..05d7886456a3 --- /dev/null +++ b/src/audio/copier/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_COPIER + bool "COPIER component" + default y + depends on IPC_MAJOR_4 + help + Select for COPIER component + +config COMP_DAI + bool "DAI component" + default y + help + Select for DAI component + +config COMP_DAI_STOP_TRIGGER_ORDER_REVERSE + bool "Reverse the ordering of DMA and DAI triggers during STOP/PAUSE" + help + Select if the ordering of DMA and DAI triggers during stop/pause should be reversed. + The normal order during stop/pause is to stop DAI before stopping DMA. This option will + allow reversing the order to do DMA stop before stopping DAI. + +config COMP_DAI_GROUP + bool "DAI Grouping support" + default y + help + Select for grouping physical DAIs into a logical DAI that can be + triggered atomically to synchronise stream start and stop operations. diff --git a/src/audio/crossover/Kconfig b/src/audio/crossover/Kconfig new file mode 100644 index 000000000000..ceff5914455f --- /dev/null +++ b/src/audio/crossover/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_CROSSOVER + bool "Crossover Filter component" + select COMP_BLOB + select MATH_IIR_DF2T + default n + help + Select for Crossover Filter component. A crossover can be used to + split a signal into two or more frequency ranges, so that the outputs + can be sent to drivers that are designed for those ranges. diff --git a/src/audio/dcblock/Kconfig b/src/audio/dcblock/Kconfig new file mode 100644 index 000000000000..7a4113153b51 --- /dev/null +++ b/src/audio/dcblock/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_DCBLOCK + bool "DC Blocking Filter component" + default y + help + Select for DC Blocking Filter component. This component filters out + the DC offset which often originates from a microphone's output. diff --git a/src/audio/drc/Kconfig b/src/audio/drc/Kconfig new file mode 100644 index 000000000000..c34da85e1bb5 --- /dev/null +++ b/src/audio/drc/Kconfig @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_DRC + bool "Dynamic Range Compressor component" + select CORDIC_FIXED + select NUMBERS_NORM + select MATH_DECIBELS + select COMP_BLOB + default n + help + Select for Dynamic Range Compressor (DRC) component. A DRC can be used + to reduce the volume of loud sounds and amplify silent sounds thus + compressing an audio signal's dynamic range. + +config DRC_MAX_PRE_DELAY_FRAMES + depends on COMP_DRC + int "DRC max number of pre-delay frames" + default 512 + help + Determines the length of pre-delay frame buffers which are allocated + runtime on DRC setup. It requires to be a 2^N number. 512 is + suggested by inference to avoid memory waste and provide reasonable + length for pre-delay frames. diff --git a/src/audio/eq_fir/Kconfig b/src/audio/eq_fir/Kconfig new file mode 100644 index 000000000000..49ae33e98c81 --- /dev/null +++ b/src/audio/eq_fir/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_FIR + bool "FIR component" + select MATH_FIR + select COMP_BLOB + depends on COMP_MODULE_ADAPTER + default y + help + Select for FIR component. FIR performance can differ between DSP + ISA and compiler used. FIR will perform best when MAC instructions + are available in ISA and are used by the compiler. i.e. xt-xcc on + xtensa will generate MAC instructions but GCC on xtensa won't. + Filter tap count can be severely restricted to reduce FIR cycles + and FIR performance for DSP/compilers with no MAC support diff --git a/src/audio/eq_iir/Kconfig b/src/audio/eq_iir/Kconfig new file mode 100644 index 000000000000..6c93059d9be8 --- /dev/null +++ b/src/audio/eq_iir/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_IIR + bool "IIR component" + select COMP_BLOB + default y + depends on COMP_MODULE_ADAPTER + select MATH_IIR_DF1 + help + Select for IIR component diff --git a/src/audio/igo_nr/Kconfig b/src/audio/igo_nr/Kconfig new file mode 100644 index 000000000000..9dd2dacf48a3 --- /dev/null +++ b/src/audio/igo_nr/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_IGO_NR + bool "IGO NR component" + select COMP_BLOB + select COMP_IGO_NR_STUB if COMP_STUBS + default n + help + This option enables Intelligo non-speech noise reduction. The feature links to a proprietary + binary libigonr.a that currently is supported on different Xtensa DSP platforms. Please email + info@intelli-go.com for any questions about the binary. + +config COMP_IGO_NR_STUB + bool "IGO NR component" + select COMP_BLOB + depends on COMP_IGO_NR + default n + help + This option builds the IGO adapter with a stub library, it should only be used for + testing or CI purposes. diff --git a/src/audio/mfcc/Kconfig b/src/audio/mfcc/Kconfig new file mode 100644 index 000000000000..7dfff67727b4 --- /dev/null +++ b/src/audio/mfcc/Kconfig @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MFCC + bool "MFCC component" + depends on COMP_MODULE_ADAPTER + select CORDIC_FIXED + select MATH_16BIT_MEL_FILTERBANK + select MATH_AUDITORY + select MATH_DCT + select MATH_DECIBELS + select MATH_FFT + select MATH_MATRIX + select MATH_WINDOW + select NATURAL_LOGARITHM_FIXED + select NUMBERS_NORM + select SQRT_FIXED + default y + help + This option enables build of a Mel-frequency cepstral coefficients + (MFCC) audio features extractor component. It converts the input + audio stream into encoded audio data for cepstral coefficients. + The characteristic of the audio features are defined in the binary + control blob. Directory tools/tune/mfcc contains a tool to create + the configurations. diff --git a/src/audio/mixer/Kconfig b/src/audio/mixer/Kconfig new file mode 100644 index 000000000000..272e9718de52 --- /dev/null +++ b/src/audio/mixer/Kconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MIXER + bool "Mixer component" + default y + help + Select for Mixer component diff --git a/src/audio/mixin_mixout/Kconfig b/src/audio/mixin_mixout/Kconfig new file mode 100644 index 000000000000..ba1b1bfda9fe --- /dev/null +++ b/src/audio/mixin_mixout/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_ARIA + bool "ARIA component" + default n + depends on IPC_MAJOR_4 + help + Select for Automatic Regressive Input Amplifier Module component + ARIA applies variable gain into incoming signal. + Applied gain is in range <1, 2 power attenuation> + Currently ARIA introduces gain transition and algorithmic + latency equal to 1 ms. diff --git a/src/audio/multiband_drc/Kconfig b/src/audio/multiband_drc/Kconfig new file mode 100644 index 000000000000..175a6bf09c48 --- /dev/null +++ b/src/audio/multiband_drc/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MULTIBAND_DRC + depends on COMP_IIR && COMP_CROSSOVER && COMP_DRC + bool "Multiband Dynamic Range Compressor component" + select CORDIC_FIXED + select COMP_BLOB + default n + help + Select for Multiband Dynamic Range Compressor (DRC) component. It + consists of Emphasis Equalizer, n-way Crossover Filter, per-band DRC, + and Deemphasis Equalizer. diff --git a/src/audio/mux/Kconfig b/src/audio/mux/Kconfig new file mode 100644 index 000000000000..ab5051707c6f --- /dev/null +++ b/src/audio/mux/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MUX + bool "MUX component" + select COMP_BLOB + depends on COMP_MODULE_ADAPTER + default y + help + Select for MUX component diff --git a/src/audio/rtnr/Kconfig b/src/audio/rtnr/Kconfig new file mode 100644 index 000000000000..70ef874af355 --- /dev/null +++ b/src/audio/rtnr/Kconfig @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_RTNR + bool "RTNR component" + select COMP_BLOB + select COMP_RTNR_STUB if COMP_STUBS + default n + help + Select for Realtek noise reduction/suppression(NR/NS) component. + Noise Suppression technology reduces stationary and transient noises in + single-channel speech signals, which increases the signal-to-noise ratio, + improves speech intelligibility and reduces listening fatigue. It estimates + ambient noise and signal levels and then passes or attenuates the signals + according to improve signal-to-noise ratios. The feature links to a + proprietary binary libSOF_RTK_MA_API.a, libSuite_rename.a, libNet.a and libPreset.a. + Please contact antz0525@realtek.com for any question about the binary. + +config COMP_RTNR_STUB + bool "RTNR component stub" + select COMP_BLOB + depends on COMP_RTNR + default n + help + Stub out the RTNR library for testing and CI purposes. diff --git a/src/audio/selector/Kconfig b/src/audio/selector/Kconfig new file mode 100644 index 000000000000..9624e5401009 --- /dev/null +++ b/src/audio/selector/Kconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_SEL + bool "Channel selector component" + default y + help + Select for SEL component diff --git a/src/audio/smart_amp/Kconfig b/src/audio/smart_amp/Kconfig index 02cc6fadc0c5..6f947650d48d 100644 --- a/src/audio/smart_amp/Kconfig +++ b/src/audio/smart_amp/Kconfig @@ -1,5 +1,18 @@ # SPDX-License-Identifier: BSD-3-Clause +config COMP_SMART_AMP + bool "Smart Amplifier component" + select COMP_BLOB + default n + help + Select for Smart Amp component. This component protect the speaker + from overheating and excursion violation. This consists of two parts + which are feedforward processing block running on playback thread + and feedback processing block running on capture thread with amp + current and voltage feedback. The internal design of this component + depends on the applied Amplifier HW solution, which should be provided + by the solution supplier respectively. + if COMP_SMART_AMP choice diff --git a/src/audio/src/Kconfig b/src/audio/src/Kconfig new file mode 100644 index 000000000000..1c0e24af15a3 --- /dev/null +++ b/src/audio/src/Kconfig @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_SRC + bool "SRC component" + default y + help + Select for SRC component + +config COMP_SRC_LITE + bool "SRC_LITE component" + default y + help + Select for SRC_LITE component + which only supports a subset of conversions + supported by the SRC module: + 48 -> 16kHz + 44.1 -> 16 kHz + 32 -> 16 kHz + 44.1 -> 48 +if COMP_SRC + +choice + prompt "SRC coefficient set" + default COMP_SRC_STD + +config COMP_SRC_STD + bool "Full conversions support and high quality" + help + This coefficients set supports a large number of conversions + with 8 - 192 kHz input and 8 - 48 kHz output. The coefficients + are 32 bits for high conversion quality. The coefficients + storage consume 79 kB. The runtime needs 8 kB. Use this if there + is critical quality usage for SRC like music via headphones and + need high sample rates. + +config COMP_SRC_SMALL + bool "Smaller conversions support and high quality" + help + This coefficients set supports a small number of conversions + with 8 - 48 kHz input and output. The coefficients are 32 bits + for high conversion quality. The coefficients storage consumes + 30 kB RAM. Runtime needs 4 kB. Use this if there is critical + quality usage for SRC like music via headphones. + +config COMP_SRC_TINY + bool "Reduced conversions support and reduced quality" + help + This coefficients set supports a minimum number of conversions + with 8 - 48 kHz input and output. The coefficients are 16 bits + that restricts the possible stop-attenuation and could cause + some audible aliasing. The bandwidth of the filters is restricted + so the full 20 kHz band is not met even if sample rate would + allow. The coefficients storage consumes 5 kB RAM. The runtime + needs 6 kB. Use this to save RAM for other applications when SRC + has no critical usage or when only need with lower quality + endpoint like miniature speakers. + +config COMP_SRC_IPC4_FULL_MATRIX + bool "Full IPC4 conversions matrix support and high quality" + help + This coefficients set supports a large number of conversions + with 8 - 192 kHz input 8 - 192 kHz output. The 32 bits coefficients + storate consumes 241 kB. The runtime needs 9 kB. Use this to + make the full conversions set available for IPC4 build. + +endchoice + +endif # SRC diff --git a/src/audio/tdfb/Kconfig b/src/audio/tdfb/Kconfig new file mode 100644 index 000000000000..f30f8aa4fe8a --- /dev/null +++ b/src/audio/tdfb/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_TDFB + bool "TDFB component" + depends on COMP_MODULE_ADAPTER + select MATH_FIR + select MATH_IIR_DF1 + select SQRT_FIXED + select CORDIC_FIXED + select COMP_BLOB + default y + help + Select for time domain fixed beamformer (TDFB) component. The + beamformer component enhances microphone capture by spatial + suppression of noise and improvement of signal-to-noise ratio of + capture from beam direction. The component is essentially a generic + single rate FIR filter bank that performs microphone array + directivity enhancement when programmed with suitable configuration + for channels selection, channel filter coefficients, and output + streams mixing. diff --git a/src/audio/up_down_mixer/Kconfig b/src/audio/up_down_mixer/Kconfig new file mode 100644 index 000000000000..38ce5adafb51 --- /dev/null +++ b/src/audio/up_down_mixer/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_UP_DOWN_MIXER + bool "UP_DOWN_MIXER component" + default n + depends on IPC_MAJOR_4 + help + Select for Up Down Mixer component Conversions supported: + Up/Downmixing for stereo output: + 1, 2, 2.1, 3.0, 3.1, Quatro, 4.0, 5.0, 5.1, 7.1 -> 2 + Upmixing for multichannel output: + 1, 2 -> 5.1 + 2 -> 7.1 + Downmixing for mono output: + 4.0, Quatro, 3.1, 2 -> 1 From 173adc990c680862715cb7811504e6caff1cc5fc Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Wed, 8 Nov 2023 13:27:24 +0800 Subject: [PATCH 05/48] base_fw: sync config from ref fw Update the basefw config query. Signed-off-by: Rander Wang --- src/include/ipc4/base_fw.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index 3c4a953405e2..1a2c67ce966d 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -359,6 +359,12 @@ enum ipc4_fw_config_params { IPC4_TELEMETRY_BUFFER_SIZE = 24, /* HW version information */ IPC4_BUS_HARDWARE_ID = 25, + /* Total memory size available in debug window */ + IPC4_DEBUG_WINDOW_SIZE = 26, + /* Number of realtime Key Phrase Buffer (KPB) output pins */ + IPC4_KPB_RT_SINK_COUNT = 27, + /* Manual control of DMI L1 state */ + IPC4_DMI_FORCE_L1_EXIT = 28, /* Total number of FW config parameters */ IPC4_FW_CFG_PARAMS_COUNT, /* Max config parameter id */ From 472458ef71a882ffeb089348e9b01c6c67907e01 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Wed, 1 Nov 2023 11:08:32 +0800 Subject: [PATCH 06/48] basefw: add support for fw config query for context save If CONFIG_ADSP_IMR_CONTEXT_SAVE is enabled, base fw will report fw_context_save is supported to host. Driver will assume fw doesn't support this feature if it is not reported. Signed-off-by: Rander Wang --- src/audio/base_fw.c | 4 ++++ src/include/ipc4/base_fw.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index ce7b5ca7778e..dc2d282be4c7 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -111,6 +111,10 @@ static int basefw_config(uint32_t *data_offset, char *data) sche_cfg.sys_tick_source = SOF_SCHEDULE_LL_TIMER; tlv_value_set(tuple, IPC4_SCHEDULER_CONFIGURATION, sizeof(sche_cfg), &sche_cfg); + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_FW_CONTEXT_SAVE, + IS_ENABLED(CONFIG_ADSP_IMR_CONTEXT_SAVE)); + tuple = tlv_next(tuple); *data_offset = (int)((char *)tuple - data); diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index 1a2c67ce966d..5aa1f168b675 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -365,6 +365,8 @@ enum ipc4_fw_config_params { IPC4_KPB_RT_SINK_COUNT = 27, /* Manual control of DMI L1 state */ IPC4_DMI_FORCE_L1_EXIT = 28, + /* FW context save on D3 entry */ + IPC4_FW_CONTEXT_SAVE = 29, /* Total number of FW config parameters */ IPC4_FW_CFG_PARAMS_COUNT, /* Max config parameter id */ From 16d126a36fd82113a7f09c2c9d490309a62d0ca4 Mon Sep 17 00:00:00 2001 From: Pawel Dobrowolski Date: Thu, 5 Oct 2023 14:20:25 +0200 Subject: [PATCH 07/48] audio: Header files cleanup Removed unused includes from a header files. Signed-off-by: Pawel Dobrowolski --- src/include/ipc4/up_down_mixer.h | 1 - .../coefficients/up_down_mixer/up_down_mixer.h | 1 - src/include/sof/audio/component.h | 16 ---------------- src/include/sof/audio/component_ext.h | 4 ---- .../sof/audio/up_down_mixer/up_down_mixer.h | 3 --- src/include/sof/common.h | 1 - 6 files changed, 26 deletions(-) diff --git a/src/include/ipc4/up_down_mixer.h b/src/include/ipc4/up_down_mixer.h index a4e2246016bd..afd913b6c0d6 100644 --- a/src/include/ipc4/up_down_mixer.h +++ b/src/include/ipc4/up_down_mixer.h @@ -7,7 +7,6 @@ #ifndef __SOF_IPC4_UP_DOWN_MIXER_H__ #define __SOF_IPC4_UP_DOWN_MIXER_H__ -#include #include "base-config.h" /** diff --git a/src/include/sof/audio/coefficients/up_down_mixer/up_down_mixer.h b/src/include/sof/audio/coefficients/up_down_mixer/up_down_mixer.h index 7344039b640d..ed6730502a79 100644 --- a/src/include/sof/audio/coefficients/up_down_mixer/up_down_mixer.h +++ b/src/include/sof/audio/coefficients/up_down_mixer/up_down_mixer.h @@ -6,7 +6,6 @@ // Author: Adrian Bonislawski #include -#include #include #if CONFIG_COMP_UP_DOWN_MIXER diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index a872e1d3048e..59214f3d2ee9 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -19,29 +19,13 @@ #include #include #include -#include #include -#include -#include -#include -#include #include -#include -#include -#include #include -#include -#include #include -#include #include #include -#include -#include -#include -#include -#include #include struct comp_dev; diff --git a/src/include/sof/audio/component_ext.h b/src/include/sof/audio/component_ext.h index 2c51943413c3..208be66b1f8d 100644 --- a/src/include/sof/audio/component_ext.h +++ b/src/include/sof/audio/component_ext.h @@ -17,11 +17,7 @@ #define __SOF_AUDIO_COMPONENT_INT_H__ #include -#include -#include #include -#include -#include /** \addtogroup component_api_helpers Component Mgmt API * @{ diff --git a/src/include/sof/audio/up_down_mixer/up_down_mixer.h b/src/include/sof/audio/up_down_mixer/up_down_mixer.h index f2d9c2fb893f..3542b6d1acf5 100644 --- a/src/include/sof/audio/up_down_mixer/up_down_mixer.h +++ b/src/include/sof/audio/up_down_mixer/up_down_mixer.h @@ -10,14 +10,11 @@ #include #include -#include #include -#include #include #include #include #include -#include #include #include diff --git a/src/include/sof/common.h b/src/include/sof/common.h index 6a875f5a90f7..5c10ba049716 100644 --- a/src/include/sof/common.h +++ b/src/include/sof/common.h @@ -27,7 +27,6 @@ #if !defined(__ASSEMBLER__) && defined(__XTENSA__) #include -#include #define VERIFY_ALIGN #endif From e4ae7ecae955572fc1825322bcc54ec17ab57da3 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 6 Oct 2023 13:23:28 +0200 Subject: [PATCH 08/48] module: Move ip4/base-config headers to module Moved header files to the module directory to separate an shared interface used by sof and native loadable modules. Signed-off-by: Adrian Warecki --- src/include/ipc4/base-config.h | 219 +---------------------- src/include/module/ipc4/base-config.h | 240 ++++++++++++++++++++++++++ 2 files changed, 244 insertions(+), 215 deletions(-) create mode 100644 src/include/module/ipc4/base-config.h diff --git a/src/include/ipc4/base-config.h b/src/include/ipc4/base-config.h index d28728c3e63f..b95ecbd3e1f9 100644 --- a/src/include/ipc4/base-config.h +++ b/src/include/ipc4/base-config.h @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2021 Intel Corporation. All rights reserved. +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 - 2023 Intel Corporation. All rights reserved. */ /* @@ -24,219 +24,8 @@ #ifndef __SOF_IPC4_BASE_CONFIG_H__ #define __SOF_IPC4_BASE_CONFIG_H__ -#include #include - -enum ipc4_sampling_frequency { - IPC4_FS_8000HZ = 8000, - IPC4_FS_11025HZ = 11025, - IPC4_FS_12000HZ = 12000, /**< Mp3, AAC, SRC only */ - IPC4_FS_16000HZ = 16000, - IPC4_FS_18900HZ = 18900, /**< SRC only for 44100 */ - IPC4_FS_22050HZ = 22050, - IPC4_FS_24000HZ = 24000, /**< Mp3, AAC, SRC only */ - IPC4_FS_32000HZ = 32000, - IPC4_FS_37800HZ = 37800, /**< SRC only for 44100 */ - IPC4_FS_44100HZ = 44100, - IPC4_FS_48000HZ = 48000, /**< Default */ - IPC4_FS_64000HZ = 64000, /**< AAC, SRC only */ - IPC4_FS_88200HZ = 88200, /**< AAC, SRC only */ - IPC4_FS_96000HZ = 96000, /**< AAC, SRC only */ - IPC4_FS_176400HZ = 176400, /**< SRC only */ - IPC4_FS_192000HZ = 192000, /**< SRC only */ - IPC4_FS_INVALID -}; - -enum ipc4_bit_depth { - IPC4_DEPTH_8BIT = 8, /**< 8 bits depth */ - IPC4_DEPTH_16BIT = 16, /**< 16 bits depth */ - IPC4_DEPTH_24BIT = 24, /**< 24 bits depth - Default */ - IPC4_DEPTH_32BIT = 32, /**< 32 bits depth */ - IPC4_DEPTH_64BIT = 64, /**< 64 bits depth */ - IPC4_DEPTH_INVALID -}; - -enum ipc4_channel_config { - IPC4_CHANNEL_CONFIG_MONO = 0, /**< one channel only */ - IPC4_CHANNEL_CONFIG_STEREO = 1, /**< L & R */ - IPC4_CHANNEL_CONFIG_2_POINT_1 = 2, /**< L, R & LFE; PCM only */ - IPC4_CHANNEL_CONFIG_3_POINT_0 = 3, /**< L, C & R; MP3 & AAC only */ - IPC4_CHANNEL_CONFIG_3_POINT_1 = 4, /**< L, C, R & LFE; PCM only */ - IPC4_CHANNEL_CONFIG_QUATRO = 5, /**< L, R, Ls & Rs; PCM only */ - IPC4_CHANNEL_CONFIG_4_POINT_0 = 6, /**< L, C, R & Cs; MP3 & AAC only */ - IPC4_CHANNEL_CONFIG_5_POINT_0 = 7, /**< L, C, R, Ls & Rs */ - IPC4_CHANNEL_CONFIG_5_POINT_1 = 8, /**< L, C, R, Ls, Rs & LFE */ - IPC4_CHANNEL_CONFIG_DUAL_MONO = 9, /**< one channel replicated in two */ - /**< Stereo (L,R) in 4 slots, 1st stream: [ L, R, -, - ] */ - IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10, - /**< Stereo (L,R) in 4 slots, 2nd stream: [ -, -, L, R ] */ - IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11, - IPC4_CHANNEL_CONFIG_7_POINT_1 = 12, /**< L, C, R, Ls, Rs & LFE., LS, RS */ - IPC4_CHANNEL_CONFIG_INVALID -}; - -enum ipc4_channel_index { - CHANNEL_LEFT = 0, - CHANNEL_CENTER = 1, - CHANNEL_RIGHT = 2, - CHANNEL_LEFT_SURROUND = 3, - CHANNEL_CENTER_SURROUND = 3, - CHANNEL_RIGHT_SURROUND = 4, - CHANNEL_LEFT_SIDE = 5, - CHANNEL_RIGHT_SIDE = 6, - CHANNEL_LFE = 7, - CHANNEL_INVALID = 0xF, -}; - -enum ipc4_interleaved_style { - IPC4_CHANNELS_INTERLEAVED = 0, - IPC4_CHANNELS_NONINTERLEAVED = 1, -}; - -enum ipc4_sample_type { - IPC4_TYPE_MSB_INTEGER = 0, /**< integer with Most Significant Byte first */ - IPC4_TYPE_LSB_INTEGER = 1, /**< integer with Least Significant Byte first */ - IPC4_TYPE_SIGNED_INTEGER = 2, - IPC4_TYPE_UNSIGNED_INTEGER = 3, - IPC4_TYPE_FLOAT = 4 -}; - -enum ipc4_stream_type { - IPC4_STREAM_PCM = 0, /**< PCM stream */ - IPC4_STREAM_MP3 = 1, /**< MP3 encoded stream */ - IPC4_STREAM_AAC = 2, /**< AAC encoded stream */ - /* TODO: revisit max stream type count. Currently - * it aligns with windows audio driver and we will - * update all when more types are supported - */ - IPC4_STREAM_COUNT = 3, - IPC4_STREAM_INVALID = 0xFF -}; - -struct ipc4_audio_format { - enum ipc4_sampling_frequency sampling_frequency; - enum ipc4_bit_depth depth; - uint32_t ch_map; - enum ipc4_channel_config ch_cfg; - uint32_t interleaving_style; - uint32_t channels_count : 8; - uint32_t valid_bit_depth : 8; - enum ipc4_sample_type s_type : 8; - uint32_t reserved : 8; -} __attribute__((packed, aligned(4))); - -struct ipc4_base_module_cfg { - uint32_t cpc; /**< the max count of Cycles Per Chunk processing */ - uint32_t ibs; /**< input Buffer Size (in bytes) */ - uint32_t obs; /**< output Buffer Size (in bytes) */ - uint32_t is_pages; /**< number of physical pages used */ - struct ipc4_audio_format audio_fmt; -} __attribute__((packed, aligned(4))); - -struct ipc4_input_pin_format { - uint32_t pin_index; /**< index of the pin */ - uint32_t ibs; /**< specifies input frame size (in bytes) */ - struct ipc4_audio_format audio_fmt; /**< format of the input data */ -} __attribute__((packed, aligned(4))); - -struct ipc4_output_pin_format { - uint32_t pin_index; /**< index of the pin */ - uint32_t obs; /**< specifies output frame size (in bytes) */ - struct ipc4_audio_format audio_fmt; /**< format of the output data */ -} __attribute__((packed, aligned(4))); - -struct ipc4_base_module_cfg_ext { - /* specifies number of items in input_pins array. Maximum size is 8 */ - uint16_t nb_input_pins; - /* specifies number of items in output_pins array. Maximum size is 8 */ - uint16_t nb_output_pins; - uint8_t reserved[12]; - /* Specifies format of input pins followed by output pins. - * Pin format arrays may be non-continuous i.e. may contain pin #0 format - * followed by pin #2 format in case pin #1 will not be in use. - * FW assigned format of the pin based on pin_index, not on a position of - * the item in the array. Applies to both input and output pins. - */ - uint8_t pin_formats[]; -} __attribute__((packed, aligned(4))); - -#define ipc4_calc_base_module_cfg_ext_size(in_pins, out_pins) \ - (sizeof(struct ipc4_base_module_cfg_ext) + \ - (in_pins) * sizeof(struct ipc4_input_pin_format) + \ - (out_pins) * sizeof(struct ipc4_output_pin_format)) - -/* Struct to combine the base_cfg and base_cfg_ext for easier parsing */ -struct ipc4_base_module_extended_cfg { - struct ipc4_base_module_cfg base_cfg; - struct ipc4_base_module_cfg_ext base_cfg_ext; -} __attribute__((packed, aligned(4))); - -/* This enum defines short 16bit parameters common for all modules. - * Value of module specific parameters have to be less than 0x3000. - */ -enum ipc4_base_module_params { - /* handled inside LargeConfigGet of module instance */ - IPC4_MOD_INST_PROPS = 0xFE, - /* handled inside ConfigSet of module instance */ - IPC4_MOD_INST_ENABLE = 0x3000 -}; - -struct ipc4_pin_props { - /* type of the connected stream. */ - enum ipc4_stream_type stream_type; - - /* audio format of the stream. The content is valid in case of ePcm stream_type. */ - struct ipc4_audio_format format; - - /* unique ID of the physical queue connected to the pin. - * If there is no queue connected, then -1 (invalid queue ID) is set - */ - uint32_t phys_queue_id; -} __attribute__((packed, aligned(4))); - -struct ipc4_pin_list_info { - uint32_t pin_count; - struct ipc4_pin_props pin_info[1]; -} __attribute__((packed, aligned(4))); - -/* structure describing module instance properties used in response - * to module LargeConfigGet with MOD_INST_PROPS parameter. - */ -struct ipc4_module_instance_props { - uint32_t id; - uint32_t dp_queue_type; - uint32_t queue_alignment; - uint32_t cp_usage_mask; - uint32_t stack_bytes; - uint32_t bss_total_bytes; - uint32_t bss_used_bytes; - uint32_t ibs_bytes; - uint32_t obs_bytes; - uint32_t cpc; - uint32_t cpc_peak; - struct ipc4_pin_list_info input_queues; - struct ipc4_pin_list_info output_queues; - uint32_t input_gateway; - uint32_t output_gateway; -} __attribute__((packed, aligned(4))); - -/* Reflects the last two entries in ModuleInstanceProps sttructure */ -struct ipc4_in_out_gateway { - uint32_t input_gateway; - uint32_t output_gateway; -} __attribute__((packed, aligned(4))); - -/* this structure may be used by modules to carry - * short 16bit parameters as part of the IxC register content. - */ -union ipc4_cfg_param_id_data { - uint32_t dw; - struct { - uint32_t data16 : 16; /* Input/Output small config data */ - uint32_t id : 14; /* input parameter ID */ - uint32_t _rsvd : 2; - } f; -} __attribute__((packed, aligned(4))); +#include struct sof_ipc_stream_params; void ipc4_base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, diff --git a/src/include/module/ipc4/base-config.h b/src/include/module/ipc4/base-config.h new file mode 100644 index 000000000000..f35369783e0e --- /dev/null +++ b/src/include/module/ipc4/base-config.h @@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 - 2023 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/base-config.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __MODULE_IPC4_BASE_CONFIG_H__ +#define __MODULE_IPC4_BASE_CONFIG_H__ + +#include + +enum ipc4_sampling_frequency { + IPC4_FS_8000HZ = 8000, + IPC4_FS_11025HZ = 11025, + IPC4_FS_12000HZ = 12000, /**< Mp3, AAC, SRC only */ + IPC4_FS_16000HZ = 16000, + IPC4_FS_18900HZ = 18900, /**< SRC only for 44100 */ + IPC4_FS_22050HZ = 22050, + IPC4_FS_24000HZ = 24000, /**< Mp3, AAC, SRC only */ + IPC4_FS_32000HZ = 32000, + IPC4_FS_37800HZ = 37800, /**< SRC only for 44100 */ + IPC4_FS_44100HZ = 44100, + IPC4_FS_48000HZ = 48000, /**< Default */ + IPC4_FS_64000HZ = 64000, /**< AAC, SRC only */ + IPC4_FS_88200HZ = 88200, /**< AAC, SRC only */ + IPC4_FS_96000HZ = 96000, /**< AAC, SRC only */ + IPC4_FS_176400HZ = 176400, /**< SRC only */ + IPC4_FS_192000HZ = 192000, /**< SRC only */ + IPC4_FS_INVALID +}; + +enum ipc4_bit_depth { + IPC4_DEPTH_8BIT = 8, /**< 8 bits depth */ + IPC4_DEPTH_16BIT = 16, /**< 16 bits depth */ + IPC4_DEPTH_24BIT = 24, /**< 24 bits depth - Default */ + IPC4_DEPTH_32BIT = 32, /**< 32 bits depth */ + IPC4_DEPTH_64BIT = 64, /**< 64 bits depth */ + IPC4_DEPTH_INVALID +}; + +enum ipc4_channel_config { + IPC4_CHANNEL_CONFIG_MONO = 0, /**< one channel only */ + IPC4_CHANNEL_CONFIG_STEREO = 1, /**< L & R */ + IPC4_CHANNEL_CONFIG_2_POINT_1 = 2, /**< L, R & LFE; PCM only */ + IPC4_CHANNEL_CONFIG_3_POINT_0 = 3, /**< L, C & R; MP3 & AAC only */ + IPC4_CHANNEL_CONFIG_3_POINT_1 = 4, /**< L, C, R & LFE; PCM only */ + IPC4_CHANNEL_CONFIG_QUATRO = 5, /**< L, R, Ls & Rs; PCM only */ + IPC4_CHANNEL_CONFIG_4_POINT_0 = 6, /**< L, C, R & Cs; MP3 & AAC only */ + IPC4_CHANNEL_CONFIG_5_POINT_0 = 7, /**< L, C, R, Ls & Rs */ + IPC4_CHANNEL_CONFIG_5_POINT_1 = 8, /**< L, C, R, Ls, Rs & LFE */ + IPC4_CHANNEL_CONFIG_DUAL_MONO = 9, /**< one channel replicated in two */ + /**< Stereo (L,R) in 4 slots, 1st stream: [ L, R, -, - ] */ + IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10, + /**< Stereo (L,R) in 4 slots, 2nd stream: [ -, -, L, R ] */ + IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11, + IPC4_CHANNEL_CONFIG_7_POINT_1 = 12, /**< L, C, R, Ls, Rs & LFE., LS, RS */ + IPC4_CHANNEL_CONFIG_INVALID +}; + +enum ipc4_channel_index { + CHANNEL_LEFT = 0, + CHANNEL_CENTER = 1, + CHANNEL_RIGHT = 2, + CHANNEL_LEFT_SURROUND = 3, + CHANNEL_CENTER_SURROUND = 3, + CHANNEL_RIGHT_SURROUND = 4, + CHANNEL_LEFT_SIDE = 5, + CHANNEL_RIGHT_SIDE = 6, + CHANNEL_LFE = 7, + CHANNEL_INVALID = 0xF, +}; + +enum ipc4_interleaved_style { + IPC4_CHANNELS_INTERLEAVED = 0, + IPC4_CHANNELS_NONINTERLEAVED = 1, +}; + +enum ipc4_sample_type { + IPC4_TYPE_MSB_INTEGER = 0, /**< integer with Most Significant Byte first */ + IPC4_TYPE_LSB_INTEGER = 1, /**< integer with Least Significant Byte first */ + IPC4_TYPE_SIGNED_INTEGER = 2, + IPC4_TYPE_UNSIGNED_INTEGER = 3, + IPC4_TYPE_FLOAT = 4 +}; + +enum ipc4_stream_type { + IPC4_STREAM_PCM = 0, /**< PCM stream */ + IPC4_STREAM_MP3 = 1, /**< MP3 encoded stream */ + IPC4_STREAM_AAC = 2, /**< AAC encoded stream */ + /* TODO: revisit max stream type count. Currently + * it aligns with windows audio driver and we will + * update all when more types are supported + */ + IPC4_STREAM_COUNT = 3, + IPC4_STREAM_INVALID = 0xFF +}; + +struct ipc4_audio_format { + enum ipc4_sampling_frequency sampling_frequency; + enum ipc4_bit_depth depth; + uint32_t ch_map; + enum ipc4_channel_config ch_cfg; + uint32_t interleaving_style; + uint32_t channels_count : 8; + uint32_t valid_bit_depth : 8; + enum ipc4_sample_type s_type : 8; + uint32_t reserved : 8; +} __attribute__((packed, aligned(4))); + +struct ipc4_base_module_cfg { + uint32_t cpc; /**< the max count of Cycles Per Chunk processing */ + uint32_t ibs; /**< input Buffer Size (in bytes) */ + uint32_t obs; /**< output Buffer Size (in bytes) */ + uint32_t is_pages; /**< number of physical pages used */ + struct ipc4_audio_format audio_fmt; +} __attribute__((packed, aligned(4))); + +struct ipc4_input_pin_format { + uint32_t pin_index; /**< index of the pin */ + uint32_t ibs; /**< specifies input frame size (in bytes) */ + struct ipc4_audio_format audio_fmt; /**< format of the input data */ +} __attribute__((packed, aligned(4))); + +struct ipc4_output_pin_format { + uint32_t pin_index; /**< index of the pin */ + uint32_t obs; /**< specifies output frame size (in bytes) */ + struct ipc4_audio_format audio_fmt; /**< format of the output data */ +} __attribute__((packed, aligned(4))); + +struct ipc4_base_module_cfg_ext { + /* specifies number of items in input_pins array. Maximum size is 8 */ + uint16_t nb_input_pins; + /* specifies number of items in output_pins array. Maximum size is 8 */ + uint16_t nb_output_pins; + uint8_t reserved[12]; + /* Specifies format of input pins followed by output pins. + * Pin format arrays may be non-continuous i.e. may contain pin #0 format + * followed by pin #2 format in case pin #1 will not be in use. + * FW assigned format of the pin based on pin_index, not on a position of + * the item in the array. Applies to both input and output pins. + */ + uint8_t pin_formats[]; +} __attribute__((packed, aligned(4))); + +#define ipc4_calc_base_module_cfg_ext_size(in_pins, out_pins) \ + (sizeof(struct ipc4_base_module_cfg_ext) + \ + (in_pins) * sizeof(struct ipc4_input_pin_format) + \ + (out_pins) * sizeof(struct ipc4_output_pin_format)) + +/* Struct to combine the base_cfg and base_cfg_ext for easier parsing */ +struct ipc4_base_module_extended_cfg { + struct ipc4_base_module_cfg base_cfg; + struct ipc4_base_module_cfg_ext base_cfg_ext; +} __attribute__((packed, aligned(4))); + +/* This enum defines short 16bit parameters common for all modules. + * Value of module specific parameters have to be less than 0x3000. + */ +enum ipc4_base_module_params { + /* handled inside LargeConfigGet of module instance */ + IPC4_MOD_INST_PROPS = 0xFE, + /* handled inside ConfigSet of module instance */ + IPC4_MOD_INST_ENABLE = 0x3000 +}; + +struct ipc4_pin_props { + /* type of the connected stream. */ + enum ipc4_stream_type stream_type; + + /* audio format of the stream. The content is valid in case of ePcm stream_type. */ + struct ipc4_audio_format format; + + /* unique ID of the physical queue connected to the pin. + * If there is no queue connected, then -1 (invalid queue ID) is set + */ + uint32_t phys_queue_id; +} __attribute__((packed, aligned(4))); + +struct ipc4_pin_list_info { + uint32_t pin_count; + struct ipc4_pin_props pin_info[1]; +} __attribute__((packed, aligned(4))); + +/* structure describing module instance properties used in response + * to module LargeConfigGet with MOD_INST_PROPS parameter. + */ +struct ipc4_module_instance_props { + uint32_t id; + uint32_t dp_queue_type; + uint32_t queue_alignment; + uint32_t cp_usage_mask; + uint32_t stack_bytes; + uint32_t bss_total_bytes; + uint32_t bss_used_bytes; + uint32_t ibs_bytes; + uint32_t obs_bytes; + uint32_t cpc; + uint32_t cpc_peak; + struct ipc4_pin_list_info input_queues; + struct ipc4_pin_list_info output_queues; + uint32_t input_gateway; + uint32_t output_gateway; +} __attribute__((packed, aligned(4))); + +/* Reflects the last two entries in ModuleInstanceProps sttructure */ +struct ipc4_in_out_gateway { + uint32_t input_gateway; + uint32_t output_gateway; +} __attribute__((packed, aligned(4))); + +/* this structure may be used by modules to carry + * short 16bit parameters as part of the IxC register content. + */ +union ipc4_cfg_param_id_data { + uint32_t dw; + struct { + uint32_t data16 : 16; /* Input/Output small config data */ + uint32_t id : 14; /* input parameter ID */ + uint32_t _rsvd : 2; + } f; +} __attribute__((packed, aligned(4))); + +#endif /* __MODULE_IPC4_BASE_CONFIG_H__ */ From 68798e52a6f65d3ece6e0eaf4e62cc3417ad5be8 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 6 Oct 2023 13:25:07 +0200 Subject: [PATCH 09/48] module: Move adsp_error_code header to module Moved header files to the module directory to separate an shared interface used by sof and native loadable modules. Signed-off-by: Adrian Warecki --- src/audio/module_adapter/iadk/system_agent.cpp | 2 +- .../module_adapter => module}/iadk/adsp_error_code.h | 10 ++++++---- .../sof/audio/module_adapter/iadk/system_error.h | 2 +- .../sof/audio/module_adapter/iadk/system_service.h | 2 +- .../module_adapter/library/native_system_service.h | 6 ++++-- 5 files changed, 13 insertions(+), 9 deletions(-) rename src/include/{sof/audio/module_adapter => module}/iadk/adsp_error_code.h (78%) diff --git a/src/audio/module_adapter/iadk/system_agent.cpp b/src/audio/module_adapter/iadk/system_agent.cpp index f42d0e15819e..77c0e120db9f 100644 --- a/src/audio/module_adapter/iadk/system_agent.cpp +++ b/src/audio/module_adapter/iadk/system_agent.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/include/sof/audio/module_adapter/iadk/adsp_error_code.h b/src/include/module/iadk/adsp_error_code.h similarity index 78% rename from src/include/sof/audio/module_adapter/iadk/adsp_error_code.h rename to src/include/module/iadk/adsp_error_code.h index 8dbcd2698a45..e7b820e0e416 100644 --- a/src/include/sof/audio/module_adapter/iadk/adsp_error_code.h +++ b/src/include/module/iadk/adsp_error_code.h @@ -1,10 +1,12 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2022 Intel Corporation. All rights reserved. + * Copyright(c) 2022 - 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki */ -#ifndef _ADSP_ERROR_CODE_H_ -#define _ADSP_ERROR_CODE_H_ +#ifndef __MODULE_IADK_ADSP_ERROR_CODE_H__ +#define __MODULE_IADK_ADSP_ERROR_CODE_H__ #include @@ -34,4 +36,4 @@ typedef uint32_t AdspErrorCode; /* Service is not supported on target platform. */ #define ADSP_SERVICE_UNAVAILABLE 143 -#endif /* _ADSP_ERROR_CODE_H_ */ +#endif /* __MODULE_IADK_ADSP_ERROR_CODE_H__ */ diff --git a/src/include/sof/audio/module_adapter/iadk/system_error.h b/src/include/sof/audio/module_adapter/iadk/system_error.h index 57b57b4b8afe..821f136694bb 100644 --- a/src/include/sof/audio/module_adapter/iadk/system_error.h +++ b/src/include/sof/audio/module_adapter/iadk/system_error.h @@ -7,7 +7,7 @@ #ifndef _ADSP_SYSTEM_ERROR_H_ #define _ADSP_SYSTEM_ERROR_H_ -#include "adsp_error_code.h" +#include namespace intel_adsp { diff --git a/src/include/sof/audio/module_adapter/iadk/system_service.h b/src/include/sof/audio/module_adapter/iadk/system_service.h index 54b15c0ab275..453247a38505 100644 --- a/src/include/sof/audio/module_adapter/iadk/system_service.h +++ b/src/include/sof/audio/module_adapter/iadk/system_service.h @@ -9,7 +9,7 @@ #include "logger.h" #include "adsp_stddef.h" -#include "adsp_error_code.h" +#include #include "native_system_service.h" #include diff --git a/src/include/sof/audio/module_adapter/library/native_system_service.h b/src/include/sof/audio/module_adapter/library/native_system_service.h index 6007770e208f..74f6a823192b 100644 --- a/src/include/sof/audio/module_adapter/library/native_system_service.h +++ b/src/include/sof/audio/module_adapter/library/native_system_service.h @@ -5,10 +5,12 @@ /*! \file native_system_service.h */ #ifndef NATIVE_SYSTEM_SERVICE_H #define NATIVE_SYSTEM_SERVICE_H + +#include + #include "logger.h" #include "adsp_stddef.h" -#include "adsp_error_code.h" -#include +#include /*! \brief This struct defines the obfuscating type for notifications. */ typedef struct _adsp_notification_handle {} *adsp_notification_handle; From 37dd2336c015c7f04e4e295c10155e1f7b7a6d5b Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 6 Oct 2023 13:26:46 +0200 Subject: [PATCH 10/48] module: module_adapter: Move module_interface header to module Moved header files to the module directory to separate an shared interface used by sof and native loadable modules. Signed-off-by: Adrian Warecki --- src/include/module/module/interface.h | 235 ++++++++++++++++++ .../module_adapter/module/module_interface.h | 226 +---------------- 2 files changed, 247 insertions(+), 214 deletions(-) create mode 100644 src/include/module/module/interface.h diff --git a/src/include/module/module/interface.h b/src/include/module/module/interface.h new file mode 100644 index 000000000000..c868f227db27 --- /dev/null +++ b/src/include/module/module/interface.h @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter + * Adrian Warecki + */ + +#ifndef __MODULE_MODULE_INTERFACE__ +#define __MODULE_MODULE_INTERFACE__ + +#include +#include + +/** + * \enum module_cfg_fragment_position + * \brief Fragment position in config + * MODULE_CFG_FRAGMENT_FIRST: first fragment of the large configuration + * MODULE_CFG_FRAGMENT_SINGLE: only fragment of the configuration + * MODULE_CFG_FRAGMENT_LAST: last fragment of the configuration + * MODULE_CFG_FRAGMENT_MIDDLE: intermediate fragment of the large configuration + */ +enum module_cfg_fragment_position { + MODULE_CFG_FRAGMENT_MIDDLE = 0, + MODULE_CFG_FRAGMENT_FIRST, + MODULE_CFG_FRAGMENT_LAST, + MODULE_CFG_FRAGMENT_SINGLE, +}; + +/** + * \enum module_processing_mode + * MODULE_PROCESSING_NORMAL: Indicates that module is expected to apply its custom processing on + * the input signal + * MODULE_PROCESSING_BYPASS: Indicates that module is expected to skip custom processing on + * the input signal and act as a passthrough component + */ + +enum module_processing_mode { + MODULE_PROCESSING_NORMAL = 0, + MODULE_PROCESSING_BYPASS, +}; + +/** + * \struct input_stream_buffer + * \brief Input stream buffer + */ +struct input_stream_buffer { + void *data; /* data stream buffer */ + uint32_t size; /* size of data in the buffer */ + uint32_t consumed; /* number of bytes consumed by the module */ + + /* Indicates end of stream condition has occurred on the input stream */ + bool end_of_stream; +}; + +/** + * \struct output_stream_buffer + * \brief Output stream buffer + */ +struct output_stream_buffer { + void *data; /* data stream buffer */ + uint32_t size; /* size of data in the buffer */ +}; + +struct processing_module; +struct sof_source; +struct sof_sink; + +/** + * \struct module_interface + * \brief 3rd party processing module interface + */ +struct module_interface { + /** + * Module specific initialization procedure, called as part of + * module_adapter component creation in .new() + */ + int (*init)(struct processing_module *mod); + /** + * Module specific prepare procedure, called as part of module_adapter + * component preparation in .prepare() + */ + int (*prepare)(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + + /** + * (optional) return true if the module is ready to process + * This procedure should check if the module is ready for immediate + * processing. + * + * NOTE! the call MUST NOT perform any time consuming operations + * + * this procedure will always return true for LL module + * + * For DP there's a default implementation that will do a simple check if there's + * at least IBS bytes of data on first source and at least OBS free space on first sink + * + * In case more sophisticated check is needed the method should be implemented in + * the module + */ + bool (*is_ready_to_process)(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + + /** + * Module specific processing procedure + * This procedure is responsible to consume + * samples provided by the module_adapter and produce/output the processed + * ones back to module_adapter. + * + * there are 3 versions of the procedure, the difference is the format of + * input/output data + * + * the module MUST implement one and ONLY one of them + * + * process_audio_stream and process_raw_data are depreciated and will be removed + * once pipeline learns to use module API directly (without module adapter) + * modules that need such processing should use proper wrappers + * + * process + * - sources are handlers to source API struct source*[] + * - sinks are handlers to sink API struct sink*[] + */ + int (*process)(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + + /** + * process_audio_stream (depreciated) + * - sources are input_stream_buffer[] + * - sources[].data is a pointer to audio_stream structure + * - sinks are output_stream_buffer[] + * - sinks[].data is a pointer to audio_stream structure + * + * It can be used by modules that support 1:1, 1:N, N:1 sources:sinks configuration. + */ + int (*process_audio_stream)(struct processing_module *mod, + struct input_stream_buffer *input_buffers, + int num_input_buffers, + struct output_stream_buffer *output_buffers, + int num_output_buffers); + + /** + * process_raw_data (depreciated) + * - sources are input_stream_buffer[] + * - sources[].data is a pointer to raw audio data + * - sinks are output_stream_buffer[] + * - sinks[].data is a pointer to raw audio data + */ + int (*process_raw_data)(struct processing_module *mod, + struct input_stream_buffer *input_buffers, + int num_input_buffers, + struct output_stream_buffer *output_buffers, + int num_output_buffers); + + /** + * Set module configuration for the given configuration ID + * + * If the complete configuration message is greater than MAX_BLOB_SIZE bytes, the + * transmission will be split into several smaller fragments. + * In this case the ADSP System will perform multiple calls to SetConfiguration() until + * completion of the configuration message sending. + * \note config_id indicates ID of the configuration message only on the first fragment + * sending, otherwise it is set to 0. + */ + int (*set_configuration)(struct processing_module *mod, + uint32_t config_id, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, uint8_t *response, + size_t response_size); + + /** + * Get module runtime configuration for the given configuration ID + * + * If the complete configuration message is greater than MAX_BLOB_SIZE bytes, the + * transmission will be split into several smaller fragments. + * In this case the ADSP System will perform multiple calls to GetConfiguration() until + * completion of the configuration message retrieval. + * \note config_id indicates ID of the configuration message only on the first fragment + * retrieval, otherwise it is set to 0. + */ + int (*get_configuration)(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size); + + /** + * Set processing mode for the module + */ + int (*set_processing_mode)(struct processing_module *mod, + enum module_processing_mode mode); + + /** + * Get the current processing mode for the module + */ + enum module_processing_mode (*get_processing_mode)(struct processing_module *mod); + + /** + * Module specific reset procedure, called as part of module_adapter component + * reset in .reset(). This should reset all parameters to their initial stage + * and free all memory allocated during prepare(). + */ + int (*reset)(struct processing_module *mod); + /** + * Module specific free procedure, called as part of module_adapter component + * free in .free(). This should free all memory allocated during module initialization. + */ + int (*free)(struct processing_module *mod); + /** + * Module specific bind procedure, called when modules are bound with each other + */ + int (*bind)(struct processing_module *mod, void *data); + /** + * Module specific unbind procedure, called when modules are disconnected from one another + */ + int (*unbind)(struct processing_module *mod, void *data); + + /** + * Module specific trigger procedure, called when modules are triggered + */ + int (*trigger)(struct processing_module *mod, int cmd); + + /* + * Ops relevant only for the endpoint devices such as the host copier or DAI copier. + * Other modules should not implement these. + * + * Below #ifdef is a temporary solution used until work on separating a common interface + * for loadable modules is completed. + */ +#ifdef SOF_MODULE_API_PRIVATE + const struct module_endpoint_ops *endpoint_ops; +#endif /* SOF_MODULE_PRIVATE */ +}; + +#endif /* __MODULE_MODULE_INTERFACE__ */ diff --git a/src/include/sof/audio/module_adapter/module/module_interface.h b/src/include/sof/audio/module_adapter/module/module_interface.h index 7cc165ad83ff..ccddcf6fda0a 100644 --- a/src/include/sof/audio/module_adapter/module/module_interface.h +++ b/src/include/sof/audio/module_adapter/module/module_interface.h @@ -1,13 +1,8 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2020 Intel Corporation. All rights reserved. - * - * - * \file common.h - * \brief Extract from generic.h definitions that need to be included - * in intel module adapter code. - * \author Jaroslaw Stelter +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. * + * Author: Jaroslaw Stelter */ #ifndef __SOF_MODULE_INTERFACE__ @@ -17,59 +12,20 @@ #include #include -/** - * \enum module_cfg_fragment_position - * \brief Fragment position in config - * MODULE_CFG_FRAGMENT_FIRST: first fragment of the large configuration - * MODULE_CFG_FRAGMENT_SINGLE: only fragment of the configuration - * MODULE_CFG_FRAGMENT_LAST: last fragment of the configuration - * MODULE_CFG_FRAGMENT_MIDDLE: intermediate fragment of the large configuration - */ -enum module_cfg_fragment_position { - MODULE_CFG_FRAGMENT_MIDDLE = 0, - MODULE_CFG_FRAGMENT_FIRST, - MODULE_CFG_FRAGMENT_LAST, - MODULE_CFG_FRAGMENT_SINGLE, -}; - -/** - * \enum module_processing_mode - * MODULE_PROCESSING_NORMAL: Indicates that module is expected to apply its custom processing on - * the input signal - * MODULE_PROCESSING_BYPASS: Indicates that module is expected to skip custom processing on - * the input signal and act as a passthrough component +/* + * Definition used to extend structure definitions to include fields for exclusive use by SOF. + * This is a temporary solution used until work on separating a common interface for loadable + * modules is completed. */ +#define SOF_MODULE_API_PRIVATE -enum module_processing_mode { - MODULE_PROCESSING_NORMAL = 0, - MODULE_PROCESSING_BYPASS, -}; - -/** - * \struct input_stream_buffer - * \brief Input stream buffer - */ -struct input_stream_buffer { - void *data; /* data stream buffer */ - uint32_t size; /* size of data in the buffer */ - uint32_t consumed; /* number of bytes consumed by the module */ - - /* Indicates end of stream condition has occurred on the input stream */ - bool end_of_stream; -}; - -/** - * \struct output_stream_buffer - * \brief Output stream buffer - */ -struct output_stream_buffer { - void *data; /* data stream buffer */ - uint32_t size; /* size of data in the buffer */ -}; +#include struct comp_dev; struct timestamp_data; struct dai_ts_data; +struct sof_ipc_stream_posn; + /** * \struct module_endpoint_ops * \brief Ops relevant only for the endpoint devices such as the host copier or DAI copier. @@ -147,164 +103,6 @@ struct module_endpoint_ops { int (*trigger)(struct comp_dev *dev, int cmd); }; -struct processing_module; -/** - * \struct module_interface - * \brief 3rd party processing module interface - */ -struct module_interface { - /** - * Module specific initialization procedure, called as part of - * module_adapter component creation in .new() - */ - int (*init)(struct processing_module *mod); - /** - * Module specific prepare procedure, called as part of module_adapter - * component preparation in .prepare() - */ - int (*prepare)(struct processing_module *mod, - struct sof_source **sources, int num_of_sources, - struct sof_sink **sinks, int num_of_sinks); - - /** - * (optional) return true if the module is ready to process - * This procedure should check if the module is ready for immediate - * processing. - * - * NOTE! the call MUST NOT perform any time consuming operations - * - * this procedure will always return true for LL module - * - * For DP there's a default implementation that will do a simple check if there's - * at least IBS bytes of data on first source and at least OBS free space on first sink - * - * In case more sophisticated check is needed the method should be implemented in - * the module - */ - bool (*is_ready_to_process)(struct processing_module *mod, - struct sof_source **sources, int num_of_sources, - struct sof_sink **sinks, int num_of_sinks); - - /** - * Module specific processing procedure - * This procedure is responsible to consume - * samples provided by the module_adapter and produce/output the processed - * ones back to module_adapter. - * - * there are 3 versions of the procedure, the difference is the format of - * input/output data - * - * the module MUST implement one and ONLY one of them - * - * process_audio_stream and process_raw_data are depreciated and will be removed - * once pipeline learns to use module API directly (without module adapter) - * modules that need such processing should use proper wrappers - * - * process - * - sources are handlers to source API struct source*[] - * - sinks are handlers to sink API struct sink*[] - */ - int (*process)(struct processing_module *mod, - struct sof_source **sources, int num_of_sources, - struct sof_sink **sinks, int num_of_sinks); - - /** - * process_audio_stream (depreciated) - * - sources are input_stream_buffer[] - * - sources[].data is a pointer to audio_stream structure - * - sinks are output_stream_buffer[] - * - sinks[].data is a pointer to audio_stream structure - * - * It can be used by modules that support 1:1, 1:N, N:1 sources:sinks configuration. - */ - int (*process_audio_stream)(struct processing_module *mod, - struct input_stream_buffer *input_buffers, - int num_input_buffers, - struct output_stream_buffer *output_buffers, - int num_output_buffers); - - /** - * process_raw_data (depreciated) - * - sources are input_stream_buffer[] - * - sources[].data is a pointer to raw audio data - * - sinks are output_stream_buffer[] - * - sinks[].data is a pointer to raw audio data - */ - int (*process_raw_data)(struct processing_module *mod, - struct input_stream_buffer *input_buffers, - int num_input_buffers, - struct output_stream_buffer *output_buffers, - int num_output_buffers); - - /** - * Set module configuration for the given configuration ID - * - * If the complete configuration message is greater than MAX_BLOB_SIZE bytes, the - * transmission will be split into several smaller fragments. - * In this case the ADSP System will perform multiple calls to SetConfiguration() until - * completion of the configuration message sending. - * \note config_id indicates ID of the configuration message only on the first fragment - * sending, otherwise it is set to 0. - */ - int (*set_configuration)(struct processing_module *mod, - uint32_t config_id, - enum module_cfg_fragment_position pos, uint32_t data_offset_size, - const uint8_t *fragment, size_t fragment_size, uint8_t *response, - size_t response_size); - - /** - * Get module runtime configuration for the given configuration ID - * - * If the complete configuration message is greater than MAX_BLOB_SIZE bytes, the - * transmission will be split into several smaller fragments. - * In this case the ADSP System will perform multiple calls to GetConfiguration() until - * completion of the configuration message retrieval. - * \note config_id indicates ID of the configuration message only on the first fragment - * retrieval, otherwise it is set to 0. - */ - int (*get_configuration)(struct processing_module *mod, - uint32_t config_id, uint32_t *data_offset_size, - uint8_t *fragment, size_t fragment_size); - - /** - * Set processing mode for the module - */ - int (*set_processing_mode)(struct processing_module *mod, - enum module_processing_mode mode); - - /** - * Get the current processing mode for the module - */ - enum module_processing_mode (*get_processing_mode)(struct processing_module *mod); - - /** - * Module specific reset procedure, called as part of module_adapter component - * reset in .reset(). This should reset all parameters to their initial stage - * and free all memory allocated during prepare(). - */ - int (*reset)(struct processing_module *mod); - /** - * Module specific free procedure, called as part of module_adapter component - * free in .free(). This should free all memory allocated during module initialization. - */ - int (*free)(struct processing_module *mod); - /** - * Module specific bind procedure, called when modules are bound with each other - */ - int (*bind)(struct processing_module *mod, void *data); - /** - * Module specific unbind procedure, called when modules are disconnected from one another - */ - int (*unbind)(struct processing_module *mod, void *data); - - /** - * Module specific trigger procedure, called when modules are triggered - */ - int (*trigger)(struct processing_module *mod, int cmd); - - const struct module_endpoint_ops *endpoint_ops; -}; - /* Convert first_block/last_block indicator to fragment position */ static inline enum module_cfg_fragment_position first_last_block_to_frag_pos(bool first_block, bool last_block) From af3486635ffbfdf5c47de89419942ba3ef130020 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 6 Oct 2023 13:27:00 +0200 Subject: [PATCH 11/48] module: module_adapter: Move generic header file to module Moved header files to the module directory to separate an shared interface used by sof and native loadable modules. Signed-off-by: Adrian Warecki --- src/include/module/module/base.h | 159 ++++++++++++++++++ .../sof/audio/module_adapter/module/generic.h | 125 ++------------ 2 files changed, 170 insertions(+), 114 deletions(-) create mode 100644 src/include/module/module/base.h diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h new file mode 100644 index 000000000000..56964162467f --- /dev/null +++ b/src/include/module/module/base.h @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. + * + * Author: Marcin Rajwa + * Adrian Warecki + */ + +#ifndef __MODULE_MODULE_GENERIC__ +#define __MODULE_MODULE_GENERIC__ + +#include +#include +#include + +#include "interface.h" +#include "../ipc4/base-config.h" + +#define module_get_private_data(mod) ((mod)->priv.private) +#define module_set_private_data(mod, data) ((mod)->priv.private = data) + +/** + * \struct module_config + * \brief Module config container, used for both config types. + */ +struct module_config { + size_t size; /**< Specifies the size of whole config */ + bool avail; /**< Marks config as available to use.*/ + void *data; /**< tlv config, a pointer to memory where config is stored. */ + const void *init_data; /**< Initial IPC configuration. */ +#if CONFIG_IPC_MAJOR_4 + struct ipc4_base_module_cfg base_cfg; +#endif +}; + +/* + * A structure containing a module's private data, intended for its exclusive use. + * + * This structure should contain only fields that are used be a module. + * All other fields, used exclusively by SOF must be moved to another structure! + */ +struct module_data { + void *private; /**< self object, memory tables etc here */ + struct module_config cfg; /**< module configuration data */ + + /* + * Fields below can only be accessed by the SOF and must be moved to a new structure. + * Below #ifdef is a temporary solution used until work on separating a common interface + * for loadable modules is completed. + */ +#ifdef SOF_MODULE_API_PRIVATE + enum module_state state; + size_t new_cfg_size; /**< size of new module config data */ + void *runtime_params; + const struct module_interface *ops; /**< module specific operations */ + struct module_memory memory; /**< memory allocated by module */ + struct module_processing_data mpd; /**< shared data comp <-> module */ + void *module_adapter; /**ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP + */ + struct list_item dp_queue_ll_to_dp_list; + struct list_item dp_queue_dp_to_ll_list; + }; + }; + struct comp_buffer *source_comp_buffer; /**< single source component buffer */ + struct comp_buffer *sink_comp_buffer; /**< single sink compoonent buffer */ + + /* module-specific flags for comp_verify_params() */ + uint32_t verify_params_flags; + + /* flag to indicate module does not pause */ + bool no_pause; + + /* + * flag to indicate that the sink buffer writeback should be skipped. It will be handled + * in the module's process callback + */ + bool skip_sink_buffer_writeback; + + /* + * flag to indicate that the source buffer invalidate should be skipped. It will be handled + * in the module's process callback + */ + bool skip_src_buffer_invalidate; + + /* + * True for module with one source component buffer and one sink component buffer + * to enable reduction of module processing overhead. False if component uses + * multiple buffers. + */ + bool stream_copy_single_to_single; + + /* flag to insure that module is loadable */ + bool is_native_sof; + + /* pointer to system services for loadable modules */ + uint32_t *sys_service; + + /* total processed data after stream started */ + uint64_t total_data_consumed; + uint64_t total_data_produced; + + /* max source/sinks supported by the module */ + uint32_t max_sources; + uint32_t max_sinks; +#endif /* SOF_MODULE_PRIVATE */ +}; + +#endif /* __MODULE_MODULE_GENERIC__ */ diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 90f91ab0cef7..10cbfa61acf9 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -1,11 +1,12 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2020 Intel Corporation. All rights reserved. +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. * * * \file generic.h * \brief Generic Module API header file * \author Marcin Rajwa + * \author Adrian Warecki * */ @@ -37,7 +38,6 @@ #define IS_PROCESSING_MODE_SINK_SOURCE(mod) \ (!!((struct module_data *)&(mod)->priv)->ops->process) -#define module_get_private_data(mod) (mod->priv.private) #define MAX_BLOB_SIZE 8192 #define MODULE_MAX_SOURCES 8 @@ -126,20 +126,6 @@ struct module_param { int32_t data[]; /**< A pointer to memory where config is stored.*/ }; -/** - * \struct module_config - * \brief Module config container, used for both config types. - */ -struct module_config { - size_t size; /**< Specifies the size of whole config */ - bool avail; /**< Marks config as available to use.*/ - void *data; /**< tlv config, a pointer to memory where config is stored. */ - const void *init_data; /**< Initial IPC configuration. */ -#if CONFIG_IPC_MAJOR_4 - struct ipc4_base_module_cfg base_cfg; -#endif -}; - /** * \struct module_memory * \brief module memory block - used for every memory allocated by module @@ -164,103 +150,14 @@ struct module_processing_data { void *out_buff; /**< A pointer to module output buffer. */ }; -/** private, runtime module data */ -struct module_data { - enum module_state state; - size_t new_cfg_size; /**< size of new module config data */ - void *private; /**< self object, memory tables etc here */ - void *runtime_params; - struct module_config cfg; /**< module configuration data */ - const struct module_interface *ops; /**< module specific operations */ - struct module_memory memory; /**< memory allocated by module */ - struct module_processing_data mpd; /**< shared data comp <-> module */ - void *module_adapter; /**ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP - */ - struct list_item dp_queue_ll_to_dp_list; - struct list_item dp_queue_dp_to_ll_list; - }; - }; - struct comp_buffer *source_comp_buffer; /**< single source component buffer */ - struct comp_buffer *sink_comp_buffer; /**< single sink compoonent buffer */ - - /* module-specific flags for comp_verify_params() */ - uint32_t verify_params_flags; - - /* flag to indicate module does not pause */ - bool no_pause; - - /* - * flag to indicate that the sink buffer writeback should be skipped. It will be handled - * in the module's process callback - */ - bool skip_sink_buffer_writeback; - - /* - * flag to indicate that the source buffer invalidate should be skipped. It will be handled - * in the module's process callback - */ - bool skip_src_buffer_invalidate; - - /* - * True for module with one source component buffer and one sink component buffer - * to enable reduction of module processing overhead. False if component uses - * multiple buffers. - */ - bool stream_copy_single_to_single; - - /* flag to insure that module is loadable */ - bool is_native_sof; - - /* pointer to system services for loadable modules */ - uint32_t *sys_service; - - /* total processed data after stream started */ - uint64_t total_data_consumed; - uint64_t total_data_produced; +/* + * Definition used to extend structure definitions to include fields for exclusive use by SOF. + * This is a temporary solution used until work on separating a common interface for loadable + * modules is completed. + */ +#define SOF_MODULE_API_PRIVATE - /* max source/sinks supported by the module */ - uint32_t max_sources; - uint32_t max_sinks; -}; +#include /*****************************************************************************/ /* Module generic interfaces */ From 0cfe9d95eac277ccc0ec4fb73bc52fb542c09603 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 6 Oct 2023 14:03:22 +0200 Subject: [PATCH 12/48] module: module_adapter: Move api_ver header file to module Moved header files to the module directory to separate an shared interface used by sof and native loadable modules. Signed-off-by: Adrian Warecki --- src/audio/module_adapter/module/modules.c | 2 +- .../module_api_ver.h => module/module/api_ver.h} | 10 +++++++--- src/include/sof/audio/module_adapter/module/modules.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) rename src/include/{sof/audio/module_adapter/library/module_api_ver.h => module/module/api_ver.h} (79%) diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 3a2fd29abd04..90634c2253ad 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include /* Intel module adapter is an extension to SOF module adapter component that allows to integrate * modules developed under IADK (Intel Audio Development Kit) Framework. IADK modules uses uniform diff --git a/src/include/sof/audio/module_adapter/library/module_api_ver.h b/src/include/module/module/api_ver.h similarity index 79% rename from src/include/sof/audio/module_adapter/library/module_api_ver.h rename to src/include/module/module/api_ver.h index ba6c1bcbe383..a315400df4f2 100644 --- a/src/include/sof/audio/module_adapter/library/module_api_ver.h +++ b/src/include/module/module/api_ver.h @@ -5,8 +5,12 @@ * Author: Pawel Dobrowolski */ -#ifndef __MODULE_API_VER_H__ -#define __MODULE_API_VER_H__ +#ifndef __MODULE_MODULE_API_VER_H__ +#define __MODULE_MODULE_API_VER_H__ + +#include + +#define ADSP_BUILD_INFO_FORMAT 0 /* * Api version 5.0.0 for sof loadable modules @@ -31,4 +35,4 @@ struct sof_module_api_build_info{ union sof_module_api_version api_version_number; }; -#endif /* __MODULE_API_VER_H__ */ +#endif /* __MODULE_MODULE_API_VER_H__ */ diff --git a/src/include/sof/audio/module_adapter/module/modules.h b/src/include/sof/audio/module_adapter/module/modules.h index 2c99f08a4389..07d099d4fdb9 100644 --- a/src/include/sof/audio/module_adapter/module/modules.h +++ b/src/include/sof/audio/module_adapter/module/modules.h @@ -35,7 +35,7 @@ * - Processing Module Adapter - SOF base FW side of ProcessingModuleInterface API * * Using the same philosofy loadable modules are using module adapter to interact with SOF FW. - * Module recognision is done by checking module API version defined in module_api_ver.h + * Module recognision is done by checking module API version defined in module/module/api_ver.h * with version read from elf file. */ From 60e992426bf6e8700ef6f750c5b8dc81d2b6ece0 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 3 Nov 2023 15:27:04 +0100 Subject: [PATCH 13/48] module: format: stream: audio_stream: Move some definitions to module Extracted struct sof_audio_stream_params and enum sof_ipc_frame definitions get_sample_bytes, get_sample_bitdepth and get_frame_bytes functions to a new files in the module directory to separate an shared interface used by sof and native loadable modules. Signed-off-by: Adrian Warecki --- src/include/ipc/stream.h | 15 +------ src/include/module/audio/audio_stream.h | 54 +++++++++++++++++++++++++ src/include/module/audio/format.h | 51 +++++++++++++++++++++++ src/include/module/ipc/stream.h | 25 ++++++++++++ src/include/sof/audio/audio_stream.h | 41 +------------------ src/include/sof/audio/format.h | 37 +---------------- 6 files changed, 135 insertions(+), 88 deletions(-) create mode 100644 src/include/module/audio/audio_stream.h create mode 100644 src/include/module/audio/format.h create mode 100644 src/include/module/ipc/stream.h diff --git a/src/include/ipc/stream.h b/src/include/ipc/stream.h index 1c9bd7a824ac..c397f34a1d27 100644 --- a/src/include/ipc/stream.h +++ b/src/include/ipc/stream.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 - 2023 Intel Corporation. All rights reserved. * * Author: Liam Girdwood * Keyon Jie @@ -16,6 +16,7 @@ #ifndef __IPC_STREAM_H__ #define __IPC_STREAM_H__ +#include #include #include @@ -48,18 +49,6 @@ /* generic PCM flags for runtime settings */ #define SOF_PCM_FLAG_XRUN_STOP (1 << 0) /**< Stop on any XRUN */ -/* stream PCM frame format */ -enum sof_ipc_frame { - SOF_IPC_FRAME_S16_LE = 0, - SOF_IPC_FRAME_S24_4LE, - SOF_IPC_FRAME_S32_LE, - SOF_IPC_FRAME_FLOAT, - /* other formats here */ - SOF_IPC_FRAME_S24_3LE, - SOF_IPC_FRAME_S24_4LE_MSB, - SOF_IPC_FRAME_U8, -}; - /* stream buffer format */ enum sof_ipc_buffer_format { SOF_IPC_BUFFER_INTERLEAVED, diff --git a/src/include/module/audio/audio_stream.h b/src/include/module/audio/audio_stream.h new file mode 100644 index 000000000000..0941047a6395 --- /dev/null +++ b/src/include/module/audio/audio_stream.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski + * Adrian Warecki + */ + +#ifndef __MODULE_AUDIO_AUDIO_STREAM_H__ +#define __MODULE_AUDIO_AUDIO_STREAM_H__ + +#include +#include +#include "../ipc/stream.h" + +/** + * set of parameters describing audio stream + * this structure is shared between audio_stream.h and sink/source interface + * TODO: compressed formats + */ +struct sof_audio_stream_params { + uint32_t id; + enum sof_ipc_frame frame_fmt; /**< Sample data format */ + enum sof_ipc_frame valid_sample_fmt; + + uint32_t rate; /**< Number of data frames per second [Hz] */ + uint16_t channels; /**< Number of samples in each frame */ + + /** + * align_frame_cnt indicates minimum number of frames that satisfies both byte + * align and frame align requirements. E.g: Consider an algorithm that processes + * in blocks of 3 frames configured to process 16-bit stereo using xtensa HiFi3 + * SIMD. Therefore with 16-bit stereo we have a frame size of 4 bytes, and + * SIMD intrinsic requirement of 8 bytes(2 frames) for HiFi3 and an algorithim + * requirement of 3 frames. Hence the common processing block size has to align + * with frame(1), intrinsic(2) and algorithm (3) giving us an optimum processing + * block size of 6 frames. + */ + uint16_t align_frame_cnt; + + /** + * the free/available bytes of sink/source right shift align_shift_idx, the result + * multiplied by align_frame_cnt is the frame count free/available that can meet + * the align requirement. + */ + uint16_t align_shift_idx; + + bool overrun_permitted; /**< indicates whether overrun is permitted */ + bool underrun_permitted; /**< indicates whether underrun is permitted */ + + uint32_t buffer_fmt; /**< enum sof_ipc_buffer_format */ +}; + +#endif /* __MODULE_AUDIO_AUDIO_STREAM_H__ */ diff --git a/src/include/module/audio/format.h b/src/include/module/audio/format.h new file mode 100644 index 000000000000..df6e58b4a9d5 --- /dev/null +++ b/src/include/module/audio/format.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 - 2023 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo + * Liam Girdwood + * Keyon Jie + * Adrian Warecki + */ + +#ifndef __MODULE_AUDIO_FORMAT_H__ +#define __MODULE_AUDIO_FORMAT_H__ + +#include +#include "../ipc/stream.h" + +static inline uint32_t get_sample_bytes(enum sof_ipc_frame fmt) +{ + switch (fmt) { + case SOF_IPC_FRAME_S16_LE: + return 2; + case SOF_IPC_FRAME_S24_3LE: + return 3; + case SOF_IPC_FRAME_U8: + return 1; + default: + return 4; + } +} + +static inline uint32_t get_sample_bitdepth(enum sof_ipc_frame fmt) +{ + switch (fmt) { + case SOF_IPC_FRAME_S16_LE: + return 16; + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S24_3LE: + return 24; + case SOF_IPC_FRAME_U8: + return 8; + default: + return 32; + } +} + +static inline uint32_t get_frame_bytes(enum sof_ipc_frame fmt, uint32_t channels) +{ + return get_sample_bytes(fmt) * channels; +} + +#endif /* __MODULE_AUDIO_FORMAT_H__ */ diff --git a/src/include/module/ipc/stream.h b/src/include/module/ipc/stream.h new file mode 100644 index 000000000000..86837d7ea302 --- /dev/null +++ b/src/include/module/ipc/stream.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 - 2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + * Adrian Warecki + */ + +#ifndef __MODULE_IPC_STREAM_H__ +#define __MODULE_IPC_STREAM_H__ + +/* stream PCM frame format */ +enum sof_ipc_frame { + SOF_IPC_FRAME_S16_LE = 0, + SOF_IPC_FRAME_S24_4LE, + SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_FLOAT, + /* other formats here */ + SOF_IPC_FRAME_S24_3LE, + SOF_IPC_FRAME_S24_4LE_MSB, + SOF_IPC_FRAME_U8, +}; + +#endif /* __MODULE_IPC_STREAM_H__ */ diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h index 4243c25f8350..9e6424d80a37 100644 --- a/src/include/sof/audio/audio_stream.h +++ b/src/include/sof/audio/audio_stream.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. * * Author: Karol Trzcinski */ @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -34,44 +35,6 @@ * @{ */ -/** - * set of parameters describing audio stream - * this structure is shared between audio_stream.h and sink/source interface - * TODO: compressed formats - */ -struct sof_audio_stream_params { - uint32_t id; - enum sof_ipc_frame frame_fmt; /**< Sample data format */ - enum sof_ipc_frame valid_sample_fmt; - - uint32_t rate; /**< Number of data frames per second [Hz] */ - uint16_t channels; /**< Number of samples in each frame */ - - /** - * align_frame_cnt indicates minimum number of frames that satisfies both byte - * align and frame align requirements. E.g: Consider an algorithm that processes - * in blocks of 3 frames configured to process 16-bit stereo using xtensa HiFi3 - * SIMD. Therefore with 16-bit stereo we have a frame size of 4 bytes, and - * SIMD intrinsic requirement of 8 bytes(2 frames) for HiFi3 and an algorithim - * requirement of 3 frames. Hence the common processing block size has to align - * with frame(1), intrinsic(2) and algorithm (3) giving us an optimum processing - * block size of 6 frames. - */ - uint16_t align_frame_cnt; - - /** - * the free/available bytes of sink/source right shift align_shift_idx, the result - * multiplied by align_frame_cnt is the frame count free/available that can meet - * the align requirement. - */ - uint16_t align_shift_idx; - - bool overrun_permitted; /**< indicates whether overrun is permitted */ - bool underrun_permitted; /**< indicates whether underrun is permitted */ - - uint32_t buffer_fmt; /**< enum sof_ipc_buffer_format */ -}; - /** * Audio stream is a circular buffer aware of audio format of the data * in the buffer so provides API for reading and writing not only bytes, diff --git a/src/include/sof/audio/format.h b/src/include/sof/audio/format.h index a33d3c60fce4..8174e53a4163 100644 --- a/src/include/sof/audio/format.h +++ b/src/include/sof/audio/format.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2016 Intel Corporation. All rights reserved. + * Copyright(c) 2016 - 2023 Intel Corporation. All rights reserved. * * Author: Seppo Ingalsuo * Liam Girdwood @@ -165,39 +165,4 @@ static inline int32_t sign_extend_s24(int32_t x) return (x << 8) >> 8; } -static inline uint32_t get_sample_bytes(enum sof_ipc_frame fmt) -{ - switch (fmt) { - case SOF_IPC_FRAME_S16_LE: - return 2; - case SOF_IPC_FRAME_S24_3LE: - return 3; - case SOF_IPC_FRAME_U8: - return 1; - default: - return 4; - } -} - -static inline uint32_t get_sample_bitdepth(enum sof_ipc_frame fmt) -{ - switch (fmt) { - case SOF_IPC_FRAME_S16_LE: - return 16; - case SOF_IPC_FRAME_S24_4LE: - case SOF_IPC_FRAME_S24_3LE: - return 24; - case SOF_IPC_FRAME_U8: - return 8; - default: - return 32; - } -} - -static inline uint32_t get_frame_bytes(enum sof_ipc_frame fmt, - uint32_t channels) -{ - return get_sample_bytes(fmt) * channels; -} - #endif /* __SOF_AUDIO_FORMAT_H__ */ From f21670b3b2e60cdc2e8a01ed82307b032fa1424a Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 3 Nov 2023 15:34:41 +0100 Subject: [PATCH 14/48] module: sink: source: Move sink/source api headers to module Moved header files to the module directory to separate an shared interface used by sof and native loadable modules. Signed-off-by: Adrian Warecki --- src/CMakeLists.txt | 2 + src/audio/sink_api_helper.c | 167 +----------- src/audio/source_api_helper.c | 97 +------ src/include/module/audio/sink_api.h | 251 ++++++++++++++++++ src/include/module/audio/source_api.h | 229 ++++++++++++++++ src/include/sof/audio/audio_stream.h | 2 - src/include/sof/audio/dp_queue.h | 2 - src/include/sof/audio/sink_api.h | 142 +--------- .../sof/audio/sink_api_implementation.h | 94 ------- src/include/sof/audio/source_api.h | 121 +-------- .../sof/audio/source_api_implementation.h | 96 ------- src/module/CMakeLists.txt | 3 + src/module/audio/CMakeLists.txt | 14 + src/module/audio/sink_api.c | 121 +++++++++ src/module/audio/source_api.c | 58 ++++ test/cmocka/src/audio/buffer/CMakeLists.txt | 8 + .../cmocka/src/audio/component/CMakeLists.txt | 2 + test/cmocka/src/audio/eq_fir/CMakeLists.txt | 2 + test/cmocka/src/audio/mixer/CMakeLists.txt | 2 + test/cmocka/src/audio/mux/CMakeLists.txt | 2 + .../src/audio/pcm_converter/CMakeLists.txt | 2 + test/cmocka/src/audio/pipeline/CMakeLists.txt | 6 + test/cmocka/src/audio/selector/CMakeLists.txt | 2 + test/cmocka/src/audio/volume/CMakeLists.txt | 2 + test/cmocka/src/math/fft/CMakeLists.txt | 2 + zephyr/CMakeLists.txt | 3 + 26 files changed, 742 insertions(+), 690 deletions(-) create mode 100644 src/include/module/audio/sink_api.h create mode 100644 src/include/module/audio/source_api.h delete mode 100644 src/include/sof/audio/sink_api_implementation.h delete mode 100644 src/include/sof/audio/source_api_implementation.h create mode 100644 src/module/CMakeLists.txt create mode 100644 src/module/audio/CMakeLists.txt create mode 100644 src/module/audio/sink_api.c create mode 100644 src/module/audio/source_api.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4caeabf27c54..29d1ad54a8bb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,8 @@ add_subdirectory(ipc) add_subdirectory(audio) add_subdirectory(lib) add_subdirectory(math) +add_subdirectory(module) + if(CONFIG_SAMPLES) add_subdirectory(samples) endif() diff --git a/src/audio/sink_api_helper.c b/src/audio/sink_api_helper.c index 9961ee61dcb8..5d25474ac6b8 100644 --- a/src/audio/sink_api_helper.c +++ b/src/audio/sink_api_helper.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2023 Intel Corporation. All rights reserved. -// +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ #include -#include #include +/* This file contains private sink API functions intended for use only by the sof. */ + void sink_init(struct sof_sink *sink, const struct sink_ops *ops, struct sof_audio_stream_params *audio_stream_params) { @@ -14,48 +15,6 @@ void sink_init(struct sof_sink *sink, const struct sink_ops *ops, sink->audio_stream_params = audio_stream_params; } -size_t sink_get_free_size(struct sof_sink *sink) -{ - return sink->ops->get_free_size(sink); -} - -int sink_get_buffer(struct sof_sink *sink, size_t req_size, - void **data_ptr, void **buffer_start, size_t *buffer_size) -{ - int ret; - - if (sink->requested_write_frag_size) - return -EBUSY; - - ret = sink->ops->get_buffer(sink, req_size, data_ptr, - buffer_start, buffer_size); - - if (!ret) - sink->requested_write_frag_size = req_size; - return ret; -} - -int sink_commit_buffer(struct sof_sink *sink, size_t commit_size) -{ - int ret; - - /* check if there was a buffer obtained for writing by sink_get_buffer */ - if (!sink->requested_write_frag_size) - return -ENODATA; - - /* limit size of data to be committed to previously obtained size */ - if (commit_size > sink->requested_write_frag_size) - commit_size = sink->requested_write_frag_size; - - ret = sink->ops->commit_buffer(sink, commit_size); - - if (!ret) - sink->requested_write_frag_size = 0; - - sink->num_of_bytes_processed += commit_size; - return ret; -} - size_t sink_get_num_of_processed_bytes(struct sof_sink *sink) { return sink->num_of_bytes_processed; @@ -66,128 +25,12 @@ void sink_reset_num_of_processed_bytes(struct sof_sink *sink) sink->num_of_bytes_processed = 0; } -enum sof_ipc_frame sink_get_frm_fmt(struct sof_sink *sink) -{ - return sink->audio_stream_params->frame_fmt; -} - -enum sof_ipc_frame sink_get_valid_fmt(struct sof_sink *sink) -{ - return sink->audio_stream_params->valid_sample_fmt; -} - -uint32_t sink_get_rate(struct sof_sink *sink) -{ - return sink->audio_stream_params->rate; -} - -uint32_t sink_get_channels(struct sof_sink *sink) -{ - return sink->audio_stream_params->channels; -} - -uint32_t sink_get_buffer_fmt(struct sof_sink *sink) -{ - return sink->audio_stream_params->buffer_fmt; -} - bool sink_get_overrun(struct sof_sink *sink) { return sink->audio_stream_params->overrun_permitted; } -int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt) -{ - sink->audio_stream_params->frame_fmt = frame_fmt; - - /* notify the implementation */ - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_valid_fmt(struct sof_sink *sink, - enum sof_ipc_frame valid_sample_fmt) -{ - sink->audio_stream_params->valid_sample_fmt = valid_sample_fmt; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_rate(struct sof_sink *sink, unsigned int rate) -{ - sink->audio_stream_params->rate = rate; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_channels(struct sof_sink *sink, unsigned int channels) -{ - sink->audio_stream_params->channels = channels; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt) -{ - sink->audio_stream_params->buffer_fmt = buffer_fmt; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted) -{ - sink->audio_stream_params->overrun_permitted = overrun_permitted; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -size_t sink_get_frame_bytes(struct sof_sink *sink) -{ - return get_frame_bytes(sink_get_frm_fmt(sink), - sink_get_channels(sink)); -} - -size_t sink_get_free_frames(struct sof_sink *sink) -{ - return sink_get_free_size(sink) / - sink_get_frame_bytes(sink); -} - -int sink_set_params(struct sof_sink *sink, - struct sof_ipc_stream_params *params, bool force_update) -{ - if (sink->ops->audio_set_ipc_params) - return sink->ops->audio_set_ipc_params(sink, params, force_update); - return 0; -} - -int sink_set_alignment_constants(struct sof_sink *sink, - const uint32_t byte_align, - const uint32_t frame_align_req) -{ - if (sink->ops->set_alignment_constants) - return sink->ops->set_alignment_constants(sink, byte_align, frame_align_req); - return 0; -} - void sink_set_min_free_space(struct sof_sink *sink, size_t min_free_space) { sink->min_free_space = min_free_space; } - -size_t sink_get_min_free_space(struct sof_sink *sink) -{ - return sink->min_free_space; -} - -uint32_t sink_get_id(struct sof_sink *sink) -{ - return sink->audio_stream_params->id; -} - diff --git a/src/audio/source_api_helper.c b/src/audio/source_api_helper.c index f1aec4924f9b..c7ca28c71720 100644 --- a/src/audio/source_api_helper.c +++ b/src/audio/source_api_helper.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2023 Intel Corporation. All rights reserved. -// +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ #include -#include #include +/* This file contains private source API functions intended for use only by the sof. */ + void source_init(struct sof_source *source, const struct source_ops *ops, struct sof_audio_stream_params *audio_stream_params) { @@ -15,47 +16,6 @@ void source_init(struct sof_source *source, const struct source_ops *ops, source->audio_stream_params = audio_stream_params; } -size_t source_get_data_available(struct sof_source *source) -{ - return source->ops->get_data_available(source); -} - -int source_get_data(struct sof_source *source, size_t req_size, - void const **data_ptr, void const **buffer_start, size_t *buffer_size) -{ - int ret; - - if (source->requested_read_frag_size) - return -EBUSY; - - ret = source->ops->get_data(source, req_size, data_ptr, buffer_start, buffer_size); - - if (!ret) - source->requested_read_frag_size = req_size; - return ret; -} - -int source_release_data(struct sof_source *source, size_t free_size) -{ - int ret; - - /* Check if anything was obtained before for reading by source_get_data */ - if (!source->requested_read_frag_size) - return -ENODATA; - - /* limit size of data to be freed to previously obtained size */ - if (free_size > source->requested_read_frag_size) - free_size = source->requested_read_frag_size; - - ret = source->ops->release_data(source, free_size); - - if (!ret) - source->requested_read_frag_size = 0; - - source->num_of_bytes_processed += free_size; - return ret; -} - size_t source_get_num_of_processed_bytes(struct sof_source *source) { return source->num_of_bytes_processed; @@ -66,31 +26,6 @@ void source_reset_num_of_processed_bytes(struct sof_source *source) source->num_of_bytes_processed = 0; } -enum sof_ipc_frame source_get_frm_fmt(struct sof_source *source) -{ - return source->audio_stream_params->frame_fmt; -} - -enum sof_ipc_frame source_get_valid_fmt(struct sof_source *source) -{ - return source->audio_stream_params->valid_sample_fmt; -} - -unsigned int source_get_rate(struct sof_source *source) -{ - return source->audio_stream_params->rate; -} - -unsigned int source_get_channels(struct sof_source *source) -{ - return source->audio_stream_params->channels; -} - -uint32_t source_get_buffer_fmt(struct sof_source *source) -{ - return source->audio_stream_params->buffer_fmt; -} - bool source_get_underrun(struct sof_source *source) { return source->audio_stream_params->underrun_permitted; @@ -145,18 +80,6 @@ int source_set_underrun(struct sof_source *source, bool underrun_permitted) return 0; } -size_t source_get_frame_bytes(struct sof_source *source) -{ - return get_frame_bytes(source_get_frm_fmt(source), - source_get_channels(source)); -} - -size_t source_get_data_frames_available(struct sof_source *source) -{ - return source_get_data_available(source) / - source_get_frame_bytes(source); -} - int source_set_params(struct sof_source *source, struct sof_ipc_stream_params *params, bool force_update) { @@ -178,13 +101,3 @@ void source_set_min_available(struct sof_source *source, size_t min_available) { source->min_available = min_available; } - -size_t source_get_min_available(struct sof_source *source) -{ - return source->min_available; -} - -uint32_t source_get_id(struct sof_source *source) -{ - return source->audio_stream_params->id; -} diff --git a/src/include/module/audio/sink_api.h b/src/include/module/audio/sink_api.h new file mode 100644 index 000000000000..d5fd0118b3bf --- /dev/null +++ b/src/include/module/audio/sink_api.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __MODULE_AUDIO_SINK_API_H__ +#define __MODULE_AUDIO_SINK_API_H__ + +#include +#include +#include +#include + +#include "audio_stream.h" +#include "format.h" + +/** + * this is a definition of API to sink of audio data + * + * THE SINK is any component that can store data somehow and provide a buffer to be filled + * with data at request. The sink API does not define how the data will be processed/used + * + * The user - a module - sees this API as a destination it must send data to + * The IMPLEMENTATION - audio_stream, DP Queue - sees this as a producer that + * PROVIDES data for processing + * + * Examples of components that should expose SINK api + * - /dev/null + * all the data stored in sink buffer are just simply discarded + * - I2S sender + * Data stored in sink buffer will be sent to the external world + * - a memory ring buffer + * data stored in the buffer will be sent to another module (usually using source API, but it + * does not matter in fact). + * + * The main advantage of using sink API instead of just taking pointers to the buffers is that + * the buffer may be prepared at the moment the data producer is requesting it. i.e. + * - cache may be written back/invalidated if necessary + * - data may be moved to make linear space + * - part of the buffer may be locked to prevent reading + * etc.etc. it depends on implementation of the data sink + * + * NOTE: the module should get a complete portion of space it needs for processing, fill it + * than release. The reason is - the depending on the implementation, the calls may be + * expensive - may involve some data moving in memory, cache writebacks, etc. + * + */ + +/* forward def */ +struct sof_sink; +struct sof_audio_stream_params; +struct sof_ipc_stream_params; + +/** + * this is a definition of internals of sink API + * + * The clients of stream API should use access functions provided below! + * + */ + +struct sink_ops { + /** + * see comment of sink_get_free_size() + */ + size_t (*get_free_size)(struct sof_sink *sink); + + /** + * see comment of sink_get_buffer() + */ + int (*get_buffer)(struct sof_sink *sink, size_t req_size, + void **data_ptr, void **buffer_start, size_t *buffer_size); + + /** + * see comment of sink_commit_buffer() + */ + int (*commit_buffer)(struct sof_sink *sink, size_t commit_size); + + /** + * OPTIONAL: Notification to the sink implementation about changes in audio format + * + * Once any of *audio_stream_params elements changes, the implementation of + * sink may need to perform some extra operations. + * This callback will be called immediately after any change + * + * @retval 0 if success, negative if new parameters are not supported + */ + int (*on_audio_format_set)(struct sof_sink *sink); + + /** + * OPTIONAL + * see sink_set_params comments + */ + int (*audio_set_ipc_params)(struct sof_sink *sink, + struct sof_ipc_stream_params *params, bool force_update); + + /** + * OPTIONAL + * see comment for sink_set_alignment_constants + */ + int (*set_alignment_constants)(struct sof_sink *sink, + const uint32_t byte_align, + const uint32_t frame_align_req); +}; + +/** internals of sink API. NOT TO BE MODIFIED OUTSIDE OF sink_api.c */ +struct sof_sink { + const struct sink_ops *ops; /** operations interface */ + size_t requested_write_frag_size; /** keeps number of bytes requested by get_buffer() */ + size_t num_of_bytes_processed; /** processed bytes counter */ + size_t min_free_space; /** minimum buffer space required by the module using sink + * it is module's OBS as declared in module bind IPC + */ + struct sof_audio_stream_params *audio_stream_params; /** pointer to audio params */ +}; + +/** + * + * Public functions + * + */ + +/** + * Retrieves size of free space available in sink (in bytes) + * return number of free bytes in buffer available to immediate filling + */ +static inline size_t sink_get_free_size(struct sof_sink *sink) +{ + return sink->ops->get_free_size(sink); +} + +static inline enum sof_ipc_frame sink_get_frm_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->frame_fmt; +} + +static inline uint32_t sink_get_channels(struct sof_sink *sink) +{ + return sink->audio_stream_params->channels; +} + +/** get size of a single audio frame (in bytes) */ +size_t sink_get_frame_bytes(struct sof_sink *sink); + +/** + * Retrieves size of free space available in sink (in frames) + * return number of free frames in buffer available to immediate filling + */ +size_t sink_get_free_frames(struct sof_sink *sink); + +/** + * Get a circular buffer to operate on (to write). + * + * Retrieves a fragment of circular data to be used by the caller + * After calling get_buffer, the space for data is guaranteed to be available + * for exclusive use on the caller core through provided pointer + * if the provided pointers are cached, it is guaranteed that the caller may safely use it without + * any additional cache operations + * The caller MUST take care of data circularity based on provided pointers + * + * @param sink a handler to sink + * @param [in] req_size requested size of space + * @param [out] data_ptr a pointer to the space will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_size size of circular buffer + * + * @retval -ENODATA if req_size is bigger than free space + * + */ +int sink_get_buffer(struct sof_sink *sink, size_t req_size, void **data_ptr, void **buffer_start, + size_t *buffer_size); + +/** + * Commits that the buffer previously obtained by get_buffer is filled with data + * and ready to be used + * + * @param sink a handler to sink + * @param commit_size amount of data that the caller declares as valid + * if commit_size is bigger than the amount of data obtained before by get_buffer(), only + * the amount obtained before will be committed. That means - if somebody obtained a buffer, + * filled it with data and wants to commit it in whole, it may simple call + * commit_buffer with commit_size==MAXINT + * @return proper error code (0 on success) + */ +int sink_commit_buffer(struct sof_sink *sink, size_t commit_size); + +/** set of functions for retrieve audio parameters */ +int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt); + +static inline enum sof_ipc_frame sink_get_valid_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->valid_sample_fmt; +} + +static inline uint32_t sink_get_rate(struct sof_sink *sink) +{ + return sink->audio_stream_params->rate; +} + +static inline uint32_t sink_get_buffer_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->buffer_fmt; +} + +/** + * initial set of audio parameters, provided in sof_ipc_stream_params + * + * @param sink a handler to sink + * @param params the set of parameters + * @param force_update tells the implementation that the params should override actual settings + * @return 0 if success + */ +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update); + +/** + * Set frame_align_shift and frame_align of stream according to byte_align and + * frame_align_req alignment requirement. Once the channel number,frame size + * are determined, the frame_align and frame_align_shift are determined too. + * these two feature will be used in audio_stream_get_avail_frames_aligned + * to calculate the available frames. it should be called in component prepare + * or param functions only once before stream copy. if someone forgets to call + * this first, there would be unexampled error such as nothing is copied at all. + * + * @param sink a handler to sink + * @param byte_align Processing byte alignment requirement. + * @param frame_align_req Processing frames alignment requirement. + * + * @return 0 if success + */ +int sink_set_alignment_constants(struct sof_sink *sink, + const uint32_t byte_align, + const uint32_t frame_align_req); + +int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt); +int sink_set_rate(struct sof_sink *sink, unsigned int rate); +int sink_set_channels(struct sof_sink *sink, unsigned int channels); +int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt); +int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted); +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update); + +static inline size_t sink_get_min_free_space(struct sof_sink *sink) +{ + return sink->min_free_space; +} + +static inline uint32_t sink_get_id(struct sof_sink *sink) +{ + return sink->audio_stream_params->id; +} + +#endif /* __MODULE_AUDIO_SINK_API_H__ */ diff --git a/src/include/module/audio/source_api.h b/src/include/module/audio/source_api.h new file mode 100644 index 000000000000..e4b522bdb7f0 --- /dev/null +++ b/src/include/module/audio/source_api.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __MODULE_AUDIO_SOURCE_API_H__ +#define __MODULE_AUDIO_SOURCE_API_H__ + +#include +#include +#include +#include + +#include "audio_stream.h" +#include "format.h" + +/** + * this is a definition of API to source of audio data + * + * THE SOURCE is any component in the system that have data stored somehow and can give the + * data outside at request. The source API does not define who and how has produced the data + * + * The user - a module - sees this as a producer that PROVIDES data for processing + * The IMPLEMENTATION - audio_stream, DP Queue - sees this API as a destination it must send data to + * * + * Examples of components that should expose source API: + * - DMIC + * Data are coming from the outside world, stores in tmp buffer and can be presented + * to the rest of the system using source_api + * - a memory ring buffer + * Data are coming from other module (usually using sink_api, but it does not matter in fact) + * + * The main advantage of using source API instead of just taking pointers to the data is that + * the data may be prepared at the moment the data receiver is requesting it. i.e. + * - cache may be written back/invalidated if necessary + * - data may be moved from circular to linear space + * - part of the buffer may be locked to prevent writing + * etc.etc. it depends on implementation of the data source + * + * Data in general are provided as a circular buffer and the data receiver should be able to + * deal with it. Of course if needed an implementation of source providing linear data can be + * implemented and used as a mid-layer for modules needing it. + * + * NOTE: the module should get a complete portion of data it needs for processing, process it + * than release. The reason is - the depending on the implementation, the calls may be + * expensive - may involve some data moving in memory, cache writebacks, etc. + */ + + /* forward def */ +struct sof_source; +struct sof_audio_stream_params; +struct sof_ipc_stream_params; + +/** + * this is a definition of internals of source API + * + * The clients of stream API should use access functions provided below! + * + */ + +struct source_ops { + /** + * see comment of source_get_data_available() + */ + size_t (*get_data_available)(struct sof_source *source); + + /** + * see comment of source_get_data_available() + */ + int (*get_data)(struct sof_source *source, size_t req_size, + void const **data_ptr, void const **buffer_start, size_t *buffer_size); + + /** + * see comment of source_release_data() + */ + int (*release_data)(struct sof_source *source, size_t free_size); + + /** + * OPTIONAL: Notification to the source implementation about changes in audio format + * + * Once any of *audio_stream_params elements changes, the implementation of + * source may need to perform some extra operations. + * This callback will be called immediately after any change + * + * @retval 0 if success, negative if new parameteres are not supported + */ + int (*on_audio_format_set)(struct sof_source *source); + + /** + * OPTIONAL + * see source_set_params comments + */ + int (*audio_set_ipc_params)(struct sof_source *source, + struct sof_ipc_stream_params *params, bool force_update); + + /** + * OPTIONAL + * see comment for source_set_alignment_constants + */ + int (*set_alignment_constants)(struct sof_source *source, + const uint32_t byte_align, + const uint32_t frame_align_req); +}; + +/** internals of source API. NOT TO BE MODIFIED OUTSIDE OF source_api.c */ +struct sof_source { + const struct source_ops *ops; + size_t requested_read_frag_size; /* keeps size of data obtained by get_data() */ + size_t num_of_bytes_processed; /* processed bytes counter */ + size_t min_available; /* minimum data available required by the module using + * source + * it is module's IBS as declared in module bind IPC + */ + + struct sof_audio_stream_params *audio_stream_params; +}; + +/** + * + * Public functions + * + */ + +/** + * Retrieves size of available data (in bytes) + * return number of bytes that are available for immediate use + */ +static inline size_t source_get_data_available(struct sof_source *source) +{ + return source->ops->get_data_available(source); +} + +static inline enum sof_ipc_frame source_get_frm_fmt(struct sof_source *source) +{ + return source->audio_stream_params->frame_fmt; +} + +static inline unsigned int source_get_channels(struct sof_source *source) +{ + return source->audio_stream_params->channels; +} + +/** get size of a single audio frame (in bytes) */ +size_t source_get_frame_bytes(struct sof_source *source); + +/** + * Retrieves size of available data (in frames) + * return number of frames that are available for immediate use + */ +size_t source_get_data_frames_available(struct sof_source *source); + +/** + * Retrieves a fragment of circular data to be used by the caller (to read) + * After calling get_data, the data are guaranteed to be available + * for exclusive use (read only) + * if the provided pointers are cached, it is guaranteed that the caller may safely use it without + * any additional cache operations + * + * The caller MUST take care of data circularity based on provided pointers + * + * Depending on implementation - there may be a way to have several receivers of the same + * data, as long as the receiver respects that data are read-only and won'do anything + * fancy with cache handling itself + * + * some implementation data may be stored in linear buffer + * in that case: + * data_ptr = buffer_start + * buffer_end = data_ptr + req_size + * buffer_size = req_size + * + * and the data receiver may use it as usual, rollover will simple never occur + * NOTE! the caller MUST NOT assume that pointers to start/end of the circular buffer + * are constant. They may change between calls + * + * @param source a handler to source + * @param [in] req_size requested size of data. + * @param [out] data_ptr a pointer to data will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_size size of circular buffer + * + * @retval -ENODATA if req_size is bigger than available data + */ +int source_get_data(struct sof_source *source, size_t req_size, void const **data_ptr, + void const **buffer_start, size_t *buffer_size); + +/** + * Releases fragment previously obtained by source_get_data() + * Once called, the data are no longer available for the caller + * + * @param source a handler to source + * @param free_size amount of data that the caller declares as "never needed again" + * if free_size == 0 the source implementation MUST keep all data in memory and make them + * available again at next get_data() call + * if free_size is bigger than the amount of data obtained before by get_data(), only + * the amount obtained before will be freed. That means - if somebody obtained some data, + * processed it and won't need it again, it may simple call put_data with free_size==MAXINT + * + * @return proper error code (0 on success) + */ +int source_release_data(struct sof_source *source, size_t free_size); + +/** set of functions for retrieve audio parameters */ +static inline enum sof_ipc_frame source_get_valid_fmt(struct sof_source *source) +{ + return source->audio_stream_params->valid_sample_fmt; +} + +static inline unsigned int source_get_rate(struct sof_source *source) +{ + return source->audio_stream_params->rate; +} + +static inline uint32_t source_get_buffer_fmt(struct sof_source *source) +{ + return source->audio_stream_params->buffer_fmt; +} + +static inline size_t source_get_min_available(struct sof_source *source) +{ + return source->min_available; +} + +static inline uint32_t source_get_id(struct sof_source *source) +{ + return source->audio_stream_params->id; +} + +#endif /* __MODULE_AUDIO_SOURCE_API_H__ */ diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h index 9e6424d80a37..09bfb68a038d 100644 --- a/src/include/sof/audio/audio_stream.h +++ b/src/include/sof/audio/audio_stream.h @@ -16,9 +16,7 @@ #include #include -#include #include -#include #include #include #include diff --git a/src/include/sof/audio/dp_queue.h b/src/include/sof/audio/dp_queue.h index 1c699f11e273..877613d141f9 100644 --- a/src/include/sof/audio/dp_queue.h +++ b/src/include/sof/audio/dp_queue.h @@ -9,8 +9,6 @@ #include #include -#include -#include #include #include #include diff --git a/src/include/sof/audio/sink_api.h b/src/include/sof/audio/sink_api.h index e9c1fa7e2d80..11ffc6e08c3d 100644 --- a/src/include/sof/audio/sink_api.h +++ b/src/include/sof/audio/sink_api.h @@ -7,96 +7,20 @@ #ifndef __SOF_SINK_API_H__ #define __SOF_SINK_API_H__ -#include -#include -#include -#include +#include /** - * this is a definition of API to sink of audio data + * Init of the API, must be called before any operation * - * THE SINK is any component that can store data somehow and provide a buffer to be filled - * with data at request. The sink API does not define how the data will be processed/used - * - * The user - a module - sees this API as a destination it must send data to - * The IMPLEMENTATION - audio_stream, DP Queue - sees this as a producer that - * PROVIDES data for processing - * - * Examples of components that should expose SINK api - * - /dev/null - * all the data stored in sink buffer are just simply discarded - * - I2S sender - * Data stored in sink buffer will be sent to the external world - * - a memory ring buffer - * data stored in the buffer will be sent to another module (usually using source API, but it - * does not matter in fact). - * - * The main advantage of using sink API instead of just taking pointers to the buffers is that - * the buffer may be prepared at the moment the data producer is requesting it. i.e. - * - cache may be written back/invalidated if necessary - * - data may be moved to make linear space - * - part of the buffer may be locked to prevent reading - * etc.etc. it depends on implementation of the data sink - * - * NOTE: the module should get a complete portion of space it needs for processing, fill it - * than release. The reason is - the depending on the implementation, the calls may be - * expensive - may involve some data moving in memory, cache writebacks, etc. - * - */ - -/** definition of obfsfucated handler of sink API */ -struct sof_sink; - -/* forward def */ -struct sof_ipc_stream_params; - -/** - * Retrieves size of free space available in sink (in bytes) - * return number of free bytes in buffer available to immediate filling - */ -size_t sink_get_free_size(struct sof_sink *sink); - -/** - * Retrieves size of free space available in sink (in frames) - * return number of free bytes in buffer available to immediate filling - */ -size_t sink_get_free_frames(struct sof_sink *sink); - -/** - * Get a circular buffer to operate on (to write). - * - * Retrieves a fragment of circular data to be used by the caller - * After calling get_buffer, the space for data is guaranteed to be available - * for exclusive use on the caller core through provided pointer - * if the provided pointers are cached, it is guaranteed that the caller may safely use it without - * any additional cache operations - * The caller MUST take care of data circularity based on provided pointers - * - * @param sink a handler to sink - * @param [in] req_size requested size of space - * @param [out] data_ptr a pointer to the space will be provided there - * @param [out] buffer_start pointer to circular buffer start - * @param [out] buffer_size size of circular buffer - * - * @retval -ENODATA if req_size is bigger than free space - * - */ -int sink_get_buffer(struct sof_sink *sink, size_t req_size, - void **data_ptr, void **buffer_start, size_t *buffer_size); - -/** - * Commits that the buffer previously obtained by get_buffer is filled with data - * and ready to be used - * - * @param sink a handler to sink - * @param commit_size amount of data that the caller declares as valid - * if commit_size is bigger than the amount of data obtained before by get_buffer(), only - * the amount obtained before will be committed. That means - if somebody obtained a buffer, - * filled it with data and wants to commit it in whole, it may simple call - * commit_buffer with commit_size==MAXINT - * @return proper error code (0 on success) + * @param sink pointer to the structure + * @param ops pointer to API operations + * @param audio_stream_params pointer to structure with audio parameters + * note that the audio_stream_params must be accessible by the caller core + * the implementation must ensure coherent access to the parameteres + * in case of i.e. cross core shared queue, it must be located in non-cached memory */ -int sink_commit_buffer(struct sof_sink *sink, size_t commit_size); +void sink_init(struct sof_sink *sink, const struct sink_ops *ops, + struct sof_audio_stream_params *audio_stream_params); /** * Get total number of bytes processed by the sink (meaning - committed by sink_commit_buffer()) @@ -111,56 +35,10 @@ size_t sink_get_num_of_processed_bytes(struct sof_sink *sink); */ void sink_reset_num_of_processed_bytes(struct sof_sink *sink); -/** get size of a single audio frame (in bytes) */ -size_t sink_get_frame_bytes(struct sof_sink *sink); - /** set of functions for retrieve audio parameters */ -enum sof_ipc_frame sink_get_frm_fmt(struct sof_sink *sink); -enum sof_ipc_frame sink_get_valid_fmt(struct sof_sink *sink); -uint32_t sink_get_rate(struct sof_sink *sink); -uint32_t sink_get_channels(struct sof_sink *sink); -uint32_t sink_get_buffer_fmt(struct sof_sink *sink); bool sink_get_overrun(struct sof_sink *sink); /** set of functions for setting audio parameters */ -int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt); -int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt); -int sink_set_rate(struct sof_sink *sink, unsigned int rate); -int sink_set_channels(struct sof_sink *sink, unsigned int channels); -int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted); -int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt); void sink_set_min_free_space(struct sof_sink *sink, size_t min_free_space); -size_t sink_get_min_free_space(struct sof_sink *sink); -uint32_t sink_get_id(struct sof_sink *sink); - -/** - * initial set of audio parameters, provided in sof_ipc_stream_params - * - * @param sink a handler to sink - * @param params the set of parameters - * @param force_update tells the implementation that the params should override actual settings - * @return 0 if success - */ -int sink_set_params(struct sof_sink *sink, - struct sof_ipc_stream_params *params, bool force_update); - -/** - * Set frame_align_shift and frame_align of stream according to byte_align and - * frame_align_req alignment requirement. Once the channel number,frame size - * are determined, the frame_align and frame_align_shift are determined too. - * these two feature will be used in audio_stream_get_avail_frames_aligned - * to calculate the available frames. it should be called in component prepare - * or param functions only once before stream copy. if someone forgets to call - * this first, there would be unexampled error such as nothing is copied at all. - * - * @param sink a handler to sink - * @param byte_align Processing byte alignment requirement. - * @param frame_align_req Processing frames alignment requirement. - * - * @return 0 if success - */ -int sink_set_alignment_constants(struct sof_sink *sink, - const uint32_t byte_align, - const uint32_t frame_align_req); #endif /* __SOF_SINK_API_H__ */ diff --git a/src/include/sof/audio/sink_api_implementation.h b/src/include/sof/audio/sink_api_implementation.h deleted file mode 100644 index 23cec8dbb30e..000000000000 --- a/src/include/sof/audio/sink_api_implementation.h +++ /dev/null @@ -1,94 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2023 Intel Corporation. All rights reserved. - * - */ - -#ifndef __SOF_SINK_API_IMPLEMENTATION_H__ -#define __SOF_SINK_API_IMPLEMENTATION_H__ - -#include -#include -#include - -/* forward def */ -struct sof_audio_stream_params; - -/** - * this is a definition of internals of sink API - * - * this file should be included by the implementations of sink API - * - * The clients of stream API should use functions provided in sink_api.h ONLY - * - */ - -struct sink_ops { - /** - * see comment of sink_get_free_size() - */ - size_t (*get_free_size)(struct sof_sink *sink); - - /** - * see comment of sink_get_buffer() - */ - int (*get_buffer)(struct sof_sink *sink, size_t req_size, - void **data_ptr, void **buffer_start, size_t *buffer_size); - - /** - * see comment of sink_commit_buffer() - */ - int (*commit_buffer)(struct sof_sink *sink, size_t commit_size); - - /** - * OPTIONAL: Notification to the sink implementation about changes in audio format - * - * Once any of *audio_stream_params elements changes, the implementation of - * sink may need to perform some extra operations. - * This callback will be called immediately after any change - * - * @retval 0 if success, negative if new parameters are not supported - */ - int (*on_audio_format_set)(struct sof_sink *sink); - - /** - * OPTIONAL - * see sink_set_params comments - */ - int (*audio_set_ipc_params)(struct sof_sink *sink, - struct sof_ipc_stream_params *params, bool force_update); - - /** - * OPTIONAL - * see comment for sink_set_alignment_constants - */ - int (*set_alignment_constants)(struct sof_sink *sink, - const uint32_t byte_align, - const uint32_t frame_align_req); -}; - -/** internals of sink API. NOT TO BE MODIFIED OUTSIDE OF sink_api_helper.h */ -struct sof_sink { - const struct sink_ops *ops; /** operations interface */ - size_t requested_write_frag_size; /** keeps number of bytes requested by get_buffer() */ - size_t num_of_bytes_processed; /** processed bytes counter */ - size_t min_free_space; /** minimum buffer space required by the module using sink - * it is module's OBS as declared in module bind IPC - */ - struct sof_audio_stream_params *audio_stream_params; /** pointer to audio params */ -}; - -/** - * Init of the API, must be called before any operation - * - * @param sink pointer to the structure - * @param ops pointer to API operations - * @param audio_stream_params pointer to structure with audio parameters - * note that the audio_stream_params must be accessible by the caller core - * the implementation must ensure coherent access to the parameteres - * in case of i.e. cross core shared queue, it must be located in non-cached memory - */ -void sink_init(struct sof_sink *sink, const struct sink_ops *ops, - struct sof_audio_stream_params *audio_stream_params); - -#endif /* __SOF_SINK_API_IMPLEMENTATION_H__ */ diff --git a/src/include/sof/audio/source_api.h b/src/include/sof/audio/source_api.h index de224f4bc51a..2f84e1948ebe 100644 --- a/src/include/sof/audio/source_api.h +++ b/src/include/sof/audio/source_api.h @@ -7,110 +7,20 @@ #ifndef __SOF_SOURCE_API_H__ #define __SOF_SOURCE_API_H__ -#include -#include -#include -#include +#include /** - * this is a definition of API to source of audio data - * - * THE SOURCE is any component in the system that have data stored somehow and can give the - * data outside at request. The source API does not define who and how has produced the data - * - * The user - a module - sees this as a producer that PROVIDES data for processing - * The IMPLEMENTATION - audio_stream, DP Queue - sees this API as a destination it must send data to - * * - * Examples of components that should expose source API: - * - DMIC - * Data are coming from the outside world, stores in tmp buffer and can be presented - * to the rest of the system using source_api - * - a memory ring buffer - * Data are coming from other module (usually using sink_api, but it does not matter in fact) - * - * The main advantage of using source API instead of just taking pointers to the data is that - * the data may be prepared at the moment the data receiver is requesting it. i.e. - * - cache may be written back/invalidated if necessary - * - data may be moved from circular to linear space - * - part of the buffer may be locked to prevent writing - * etc.etc. it depends on implementation of the data source - * - * Data in general are provided as a circular buffer and the data receiver should be able to - * deal with it. Of course if needed an implementation of source providing linear data can be - * implemented and used as a mid-layer for modules needing it. - * - * NOTE: the module should get a complete portion of data it needs for processing, process it - * than release. The reason is - the depending on the implementation, the calls may be - * expensive - may involve some data moving in memory, cache writebacks, etc. - */ - -/** definition of obfsfucated handler of source API */ -struct sof_source; - -/* forward def */ -struct sof_ipc_stream_params; - -/** - * Retrieves size of available data (in bytes) - * return number of bytes that are available for immediate use - */ -size_t source_get_data_available(struct sof_source *source); - -/** - * Retrieves size of available data (in frames) - * return number of bytes that are available for immediate use - */ -size_t source_get_data_frames_available(struct sof_source *source); - -/** - * Retrieves a fragment of circular data to be used by the caller (to read) - * After calling get_data, the data are guaranteed to be available - * for exclusive use (read only) - * if the provided pointers are cached, it is guaranteed that the caller may safely use it without - * any additional cache operations - * - * The caller MUST take care of data circularity based on provided pointers - * - * Depending on implementation - there may be a way to have several receivers of the same - * data, as long as the receiver respects that data are read-only and won'do anything - * fancy with cache handling itself - * - * some implementation data may be stored in linear buffer - * in that case: - * data_ptr = buffer_start - * buffer_end = data_ptr + req_size - * buffer_size = req_size - * - * and the data receiver may use it as usual, rollover will simple never occur - * NOTE! the caller MUST NOT assume that pointers to start/end of the circular buffer - * are constant. They may change between calls - * - * @param source a handler to source - * @param [in] req_size requested size of data. - * @param [out] data_ptr a pointer to data will be provided there - * @param [out] buffer_start pointer to circular buffer start - * @param [out] buffer_size size of circular buffer - * - * @retval -ENODATA if req_size is bigger than available data + * Init of the API, must be called before any operation + * + * @param source pointer to the structure + * @param ops pointer to API operations + * @param audio_stream_params pointer to structure with audio parameters + * note that the audio_stream_params must be accessible by the caller core + * the implementation must ensure coherent access to the parameteres + * in case of i.e. cross core shared queue, it must be located in non-cached memory */ -int source_get_data(struct sof_source *source, size_t req_size, - void const **data_ptr, void const **buffer_start, size_t *buffer_size); - -/** - * Releases fragment previously obtained by source_get_data() - * Once called, the data are no longer available for the caller - * - * @param source a handler to source - * @param free_size amount of data that the caller declares as "never needed again" - * if free_size == 0 the source implementation MUST keep all data in memory and make them - * available again at next get_data() call - * if free_size is bigger than the amount of data obtained before by get_data(), only - * the amount obtained before will be freed. That means - if somebody obtained some data, - * processed it and won't need it again, it may simple call put_data with free_size==MAXINT - * - * @return proper error code (0 on success) - */ -int source_release_data(struct sof_source *source, size_t free_size); +void source_init(struct sof_source *source, const struct source_ops *ops, + struct sof_audio_stream_params *audio_stream_params); /** * Get total number of bytes processed by the source (meaning - freed by source_release_data()) @@ -122,15 +32,7 @@ size_t source_get_num_of_processed_bytes(struct sof_source *source); */ void source_reset_num_of_processed_bytes(struct sof_source *source); -/** get size of a single audio frame (in bytes) */ -size_t source_get_frame_bytes(struct sof_source *source); - /** set of functions for retrieve audio parameters */ -enum sof_ipc_frame source_get_frm_fmt(struct sof_source *source); -enum sof_ipc_frame source_get_valid_fmt(struct sof_source *source); -unsigned int source_get_rate(struct sof_source *source); -unsigned int source_get_channels(struct sof_source *source); -uint32_t source_get_buffer_fmt(struct sof_source *source); bool source_get_underrun(struct sof_source *source); uint32_t source_get_id(struct sof_source *source); @@ -143,7 +45,6 @@ int source_set_channels(struct sof_source *source, unsigned int channels); int source_set_underrun(struct sof_source *source, bool underrun_permitted); int source_set_buffer_fmt(struct sof_source *source, uint32_t buffer_fmt); void source_set_min_available(struct sof_source *source, size_t min_available); -size_t source_get_min_available(struct sof_source *source); /** * initial set of audio parameters, provided in sof_ipc_stream_params diff --git a/src/include/sof/audio/source_api_implementation.h b/src/include/sof/audio/source_api_implementation.h deleted file mode 100644 index 606141c92dfb..000000000000 --- a/src/include/sof/audio/source_api_implementation.h +++ /dev/null @@ -1,96 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2023 Intel Corporation. All rights reserved. - * - */ - -#ifndef __SOF_SOURCE_API_IMPLEMENTATION_H__ -#define __SOF_SOURCE_API_IMPLEMENTATION_H__ - -#include -#include -#include - -/* forward def */ -struct sof_audio_stream_params; - -/** - * this is a definition of internals of source API - * - * this file should be included by the implementations of source API - * - * The clients of stream API should use functions provided in source_api.h ONLY - * - */ - -struct source_ops { - /** - * see comment of source_get_data_available() - */ - size_t (*get_data_available)(struct sof_source *source); - - /** - * see comment of source_get_data_available() - */ - int (*get_data)(struct sof_source *source, size_t req_size, - void const **data_ptr, void const **buffer_start, size_t *buffer_size); - - /** - * see comment of source_release_data() - */ - int (*release_data)(struct sof_source *source, size_t free_size); - - /** - * OPTIONAL: Notification to the source implementation about changes in audio format - * - * Once any of *audio_stream_params elements changes, the implementation of - * source may need to perform some extra operations. - * This callback will be called immediately after any change - * - * @retval 0 if success, negative if new parameteres are not supported - */ - int (*on_audio_format_set)(struct sof_source *source); - - /** - * OPTIONAL - * see source_set_params comments - */ - int (*audio_set_ipc_params)(struct sof_source *source, - struct sof_ipc_stream_params *params, bool force_update); - - /** - * OPTIONAL - * see comment for source_set_alignment_constants - */ - int (*set_alignment_constants)(struct sof_source *source, - const uint32_t byte_align, - const uint32_t frame_align_req); -}; - -/** internals of source API. NOT TO BE MODIFIED OUTSIDE OF source_api_helper.h */ -struct sof_source { - const struct source_ops *ops; - size_t requested_read_frag_size; /** keeps size of data obtained by get_data() */ - size_t num_of_bytes_processed; /** processed bytes counter */ - size_t min_available; /** minimum data available required by the module using - * source - * it is module's IBS as declared in module bind IPC - */ - - struct sof_audio_stream_params *audio_stream_params; -}; - -/** - * Init of the API, must be called before any operation - * - * @param source pointer to the structure - * @param ops pointer to API operations - * @param audio_stream_params pointer to structure with audio parameters - * note that the audio_stream_params must be accessible by the caller core - * the implementation must ensure coherent access to the parameteres - * in case of i.e. cross core shared queue, it must be located in non-cached memory - */ -void source_init(struct sof_source *source, const struct source_ops *ops, - struct sof_audio_stream_params *audio_stream_params); - -#endif /* __SOF_SOURCE_API_IMPLEMENTATION_H__ */ diff --git a/src/module/CMakeLists.txt b/src/module/CMakeLists.txt new file mode 100644 index 000000000000..1cdd0d2137a9 --- /dev/null +++ b/src/module/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(audio) diff --git a/src/module/audio/CMakeLists.txt b/src/module/audio/CMakeLists.txt new file mode 100644 index 000000000000..2d805aa68929 --- /dev/null +++ b/src/module/audio/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause + +is_zephyr(it_is) +if(it_is) ### Zephyr ### + zephyr_library_sources( + source_api.c + sink_api.c + ) +else() ### Not Zephyr ### + add_local_sources(sof + source_api.c + sink_api.c + ) +endif() # Zephyr diff --git a/src/module/audio/sink_api.c b/src/module/audio/sink_api.c new file mode 100644 index 000000000000..cb40405974dc --- /dev/null +++ b/src/module/audio/sink_api.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#include +#include + +/* This file contains public sink API functions that were too large to mark is as inline. */ + +int sink_get_buffer(struct sof_sink *sink, size_t req_size, + void **data_ptr, void **buffer_start, size_t *buffer_size) +{ + int ret; + + if (sink->requested_write_frag_size) + return -EBUSY; + + ret = sink->ops->get_buffer(sink, req_size, data_ptr, + buffer_start, buffer_size); + + if (!ret) + sink->requested_write_frag_size = req_size; + return ret; +} + +int sink_commit_buffer(struct sof_sink *sink, size_t commit_size) +{ + int ret; + + /* check if there was a buffer obtained for writing by sink_get_buffer */ + if (!sink->requested_write_frag_size) + return -ENODATA; + + /* limit size of data to be committed to previously obtained size */ + if (commit_size > sink->requested_write_frag_size) + commit_size = sink->requested_write_frag_size; + + ret = sink->ops->commit_buffer(sink, commit_size); + + if (!ret) + sink->requested_write_frag_size = 0; + + sink->num_of_bytes_processed += commit_size; + return ret; +} + +int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt) +{ + sink->audio_stream_params->frame_fmt = frame_fmt; + + /* notify the implementation */ + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +size_t sink_get_frame_bytes(struct sof_sink *sink) +{ + return get_frame_bytes(sink_get_frm_fmt(sink), sink_get_channels(sink)); +} + +size_t sink_get_free_frames(struct sof_sink *sink) +{ + return sink_get_free_size(sink) / sink_get_frame_bytes(sink); +} + +int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt) +{ + sink->audio_stream_params->valid_sample_fmt = valid_sample_fmt; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_rate(struct sof_sink *sink, unsigned int rate) +{ + sink->audio_stream_params->rate = rate; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_channels(struct sof_sink *sink, unsigned int channels) +{ + sink->audio_stream_params->channels = channels; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt) +{ + sink->audio_stream_params->buffer_fmt = buffer_fmt; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted) +{ + sink->audio_stream_params->overrun_permitted = overrun_permitted; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update) +{ + if (sink->ops->audio_set_ipc_params) + return sink->ops->audio_set_ipc_params(sink, params, force_update); + return 0; +} + +int sink_set_alignment_constants(struct sof_sink *sink, const uint32_t byte_align, + const uint32_t frame_align_req) +{ + if (sink->ops->set_alignment_constants) + return sink->ops->set_alignment_constants(sink, byte_align, frame_align_req); + return 0; +} diff --git a/src/module/audio/source_api.c b/src/module/audio/source_api.c new file mode 100644 index 000000000000..2f589524621f --- /dev/null +++ b/src/module/audio/source_api.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + + +#include +#include + +/* This file contains public source API functions that were too large to mark is as inline. */ + +int source_get_data(struct sof_source *source, size_t req_size, + void const **data_ptr, void const **buffer_start, size_t *buffer_size) +{ + int ret; + + if (source->requested_read_frag_size) + return -EBUSY; + + ret = source->ops->get_data(source, req_size, data_ptr, buffer_start, buffer_size); + + if (!ret) + source->requested_read_frag_size = req_size; + return ret; +} + +int source_release_data(struct sof_source *source, size_t free_size) +{ + int ret; + + /* Check if anything was obtained before for reading by source_get_data */ + if (!source->requested_read_frag_size) + return -ENODATA; + + /* limit size of data to be freed to previously obtained size */ + if (free_size > source->requested_read_frag_size) + free_size = source->requested_read_frag_size; + + ret = source->ops->release_data(source, free_size); + + if (!ret) + source->requested_read_frag_size = 0; + + source->num_of_bytes_processed += free_size; + return ret; +} + +size_t source_get_frame_bytes(struct sof_source *source) +{ + return get_frame_bytes(source_get_frm_fmt(source), + source_get_channels(source)); +} + +size_t source_get_data_frames_available(struct sof_source *source) +{ + return source_get_data_available(source) / + source_get_frame_bytes(source); +} diff --git a/test/cmocka/src/audio/buffer/CMakeLists.txt b/test/cmocka/src/audio/buffer/CMakeLists.txt index acc92539a5e6..4db02de6f571 100644 --- a/test/cmocka/src/audio/buffer/CMakeLists.txt +++ b/test/cmocka/src/audio/buffer/CMakeLists.txt @@ -8,6 +8,8 @@ cmocka_test(buffer_copy ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c @@ -30,6 +32,8 @@ cmocka_test(buffer_new ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c @@ -51,6 +55,8 @@ cmocka_test(buffer_wrap ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c @@ -72,6 +78,8 @@ cmocka_test(buffer_write ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c diff --git a/test/cmocka/src/audio/component/CMakeLists.txt b/test/cmocka/src/audio/component/CMakeLists.txt index 5eb4d19c3151..866e262f0f0a 100644 --- a/test/cmocka/src/audio/component/CMakeLists.txt +++ b/test/cmocka/src/audio/component/CMakeLists.txt @@ -19,4 +19,6 @@ cmocka_test(comp_set_state ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ) diff --git a/test/cmocka/src/audio/eq_fir/CMakeLists.txt b/test/cmocka/src/audio/eq_fir/CMakeLists.txt index 547cb7be9642..3059f45956ab 100644 --- a/test/cmocka/src/audio/eq_fir/CMakeLists.txt +++ b/test/cmocka/src/audio/eq_fir/CMakeLists.txt @@ -31,6 +31,8 @@ add_library(audio_for_eq_fir STATIC ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c diff --git a/test/cmocka/src/audio/mixer/CMakeLists.txt b/test/cmocka/src/audio/mixer/CMakeLists.txt index 01aebc99223e..a16016f70044 100644 --- a/test/cmocka/src/audio/mixer/CMakeLists.txt +++ b/test/cmocka/src/audio/mixer/CMakeLists.txt @@ -24,6 +24,8 @@ cmocka_test(mixer ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) target_link_libraries(mixer PRIVATE -lm) diff --git a/test/cmocka/src/audio/mux/CMakeLists.txt b/test/cmocka/src/audio/mux/CMakeLists.txt index c6f67ae89127..73451ba72458 100644 --- a/test/cmocka/src/audio/mux/CMakeLists.txt +++ b/test/cmocka/src/audio/mux/CMakeLists.txt @@ -18,6 +18,8 @@ add_library( ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/math/numbers.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c diff --git a/test/cmocka/src/audio/pcm_converter/CMakeLists.txt b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt index 13adc77e000c..52f268a908c5 100644 --- a/test/cmocka/src/audio/pcm_converter/CMakeLists.txt +++ b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt @@ -13,6 +13,8 @@ if(CONFIG_FORMAT_FLOAT) ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c diff --git a/test/cmocka/src/audio/pipeline/CMakeLists.txt b/test/cmocka/src/audio/pipeline/CMakeLists.txt index c8219517c19f..2f27d7cfcd74 100644 --- a/test/cmocka/src/audio/pipeline/CMakeLists.txt +++ b/test/cmocka/src/audio/pipeline/CMakeLists.txt @@ -29,6 +29,8 @@ cmocka_test(pipeline_new ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c @@ -51,6 +53,8 @@ cmocka_test(pipeline_connect_upstream ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c @@ -73,6 +77,8 @@ cmocka_test(pipeline_free ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c diff --git a/test/cmocka/src/audio/selector/CMakeLists.txt b/test/cmocka/src/audio/selector/CMakeLists.txt index 46be5bdac073..36c13759be6d 100644 --- a/test/cmocka/src/audio/selector/CMakeLists.txt +++ b/test/cmocka/src/audio/selector/CMakeLists.txt @@ -20,6 +20,8 @@ add_library(audio_for_selector STATIC ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c diff --git a/test/cmocka/src/audio/volume/CMakeLists.txt b/test/cmocka/src/audio/volume/CMakeLists.txt index f6530bc2b3b0..901bd3c2e4f2 100644 --- a/test/cmocka/src/audio/volume/CMakeLists.txt +++ b/test/cmocka/src/audio/volume/CMakeLists.txt @@ -28,6 +28,8 @@ add_library(audio_for_volume STATIC ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c diff --git a/test/cmocka/src/math/fft/CMakeLists.txt b/test/cmocka/src/math/fft/CMakeLists.txt index d21819848cd0..921698d04809 100644 --- a/test/cmocka/src/math/fft/CMakeLists.txt +++ b/test/cmocka/src/math/fft/CMakeLists.txt @@ -12,6 +12,8 @@ cmocka_test(fft ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b4d729bada78..563dc6b14622 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -397,6 +397,9 @@ zephyr_library_sources( lib.c ) +# SOF module interface functions +add_subdirectory(../src/module module_unused_install/) + if(CONFIG_ZEPHYR_DP_SCHEDULER) zephyr_library_sources(${SOF_AUDIO_PATH}/dp_queue.c) endif() From f3e095947222db2eb3063382dbee9f6341cea5af Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 6 Oct 2023 13:27:42 +0200 Subject: [PATCH 15/48] lmdk: module: Use extracted module headers in lmdk Use of a separated module headers when building native loadable libraries. Signed-off-by: Adrian Warecki --- lmdk/cmake/build.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/lmdk/cmake/build.cmake b/lmdk/cmake/build.cmake index 15369cb41dbe..e21a3ad3c610 100644 --- a/lmdk/cmake/build.cmake +++ b/lmdk/cmake/build.cmake @@ -19,6 +19,7 @@ foreach(MODULE ${MODULES_LIST}) target_include_directories(${MODULE} PRIVATE "${LMDK_BASE}/include" "${RIMAGE_INCLUDE_DIR}" + "${SOF_BASE}/src/include/module" ) # generate linker script From 4d4421a046bd681d275fb887e88a58b199870b11 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Mon, 6 Nov 2023 15:04:26 +0100 Subject: [PATCH 16/48] lmdk: Build module common functions Added building a static library containing common functions for modules provided by sof. Native loadable modules are statically linked to it. Signed-off-by: Adrian Warecki --- lmdk/cmake/build.cmake | 8 ++++++++ lmdk/cmake/config.cmake | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/lmdk/cmake/build.cmake b/lmdk/cmake/build.cmake index e21a3ad3c610..8412bf313c05 100644 --- a/lmdk/cmake/build.cmake +++ b/lmdk/cmake/build.cmake @@ -9,6 +9,11 @@ endif() include(${CMAKE_CURRENT_LIST_DIR}/config.cmake) +# Build common module functions from sof to a static library +add_library(sof STATIC) +target_include_directories(sof PRIVATE "${SOF_BASE}/src/include") +add_subdirectory("${SOF_BASE}/src/module" module_api) + foreach(MODULE ${MODULES_LIST}) add_executable(${MODULE}) add_subdirectory(${LMDK_BASE}/modules/${MODULE} ${MODULE}_module) @@ -36,6 +41,9 @@ foreach(MODULE ${MODULES_LIST}) -P ${CMAKE_CURRENT_LIST_DIR}/ldscripts.cmake ) + # Link module with sof common module functions + target_link_libraries(${MODULE} sof) + target_link_options(${MODULE} PRIVATE "-nostartfiles" "-Wl,--no-undefined" "-Wl,--unresolved-symbols=report-all" "-Wl,--error-unresolved-symbols" diff --git a/lmdk/cmake/config.cmake b/lmdk/cmake/config.cmake index 6edc79541a89..6faa6d353215 100644 --- a/lmdk/cmake/config.cmake +++ b/lmdk/cmake/config.cmake @@ -16,3 +16,22 @@ cmake_path(ABSOLUTE_PATH SOF_BASE NORMALIZE) set(RIMAGE_INCLUDE_DIR ${SOF_BASE}/tools/rimage/src/include) cmake_path(ABSOLUTE_PATH RIMAGE_INCLUDE_DIR NORMALIZE) + +# Adds sources to target like target_sources, but assumes that +# paths are relative to subdirectory. +# Works like: +# Cmake >= 3.13: +# target_sources( PRIVATE ) +# Cmake < 3.13: +# target_sources( PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/) +function(add_local_sources target) + foreach(arg ${ARGN}) + if(IS_ABSOLUTE ${arg}) + set(path ${arg}) + else() + set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) + endif() + + target_sources(${target} PRIVATE ${path}) + endforeach() +endfunction() From 807471497aacd886843620ff012def7c3c8fd854 Mon Sep 17 00:00:00 2001 From: Andrula Song Date: Wed, 15 Nov 2023 11:10:40 +0800 Subject: [PATCH 17/48] Audio: DRC: Add HiFi4 implementation of DRC Add HiFi4 implementation of DRC. Signed-off-by: Andrula Song --- src/audio/drc/CMakeLists.txt | 1 + src/audio/drc/drc_generic.c | 2 + src/audio/drc/drc_hifi4.c | 911 ++++++++++++++++++++++ src/audio/drc/drc_math_hifi3.c | 2 +- src/include/sof/audio/drc/drc_math.h | 2 +- src/include/sof/audio/drc/drc_plat_conf.h | 10 +- zephyr/CMakeLists.txt | 1 + 7 files changed, 926 insertions(+), 3 deletions(-) create mode 100644 src/audio/drc/drc_hifi4.c diff --git a/src/audio/drc/CMakeLists.txt b/src/audio/drc/CMakeLists.txt index 885c16c8b334..650b09b40612 100644 --- a/src/audio/drc/CMakeLists.txt +++ b/src/audio/drc/CMakeLists.txt @@ -1,5 +1,6 @@ add_local_sources(sof drc.c) add_local_sources(sof drc_generic.c) add_local_sources(sof drc_hifi3.c) +add_local_sources(sof drc_hifi4.c) add_local_sources(sof drc_math_generic.c) add_local_sources(sof drc_math_hifi3.c) diff --git a/src/audio/drc/drc_generic.c b/src/audio/drc/drc_generic.c index 472431a0e408..1cb4910425cf 100644 --- a/src/audio/drc/drc_generic.c +++ b/src/audio/drc/drc_generic.c @@ -449,6 +449,7 @@ void drc_compress_output(struct drc_state *state, #endif /* DRC_GENERIC */ +#if DRC_GENERIC || DRC_HIFI3 /* After one complete division of samples have been received (and one division of * samples have been output), we calculate shaped power average * (detector_average) from the input division, update envelope parameters from @@ -782,3 +783,4 @@ const struct drc_proc_fnmap drc_proc_fnmap[] = { }; const size_t drc_proc_fncount = ARRAY_SIZE(drc_proc_fnmap); +#endif diff --git a/src/audio/drc/drc_hifi4.c b/src/audio/drc/drc_hifi4.c new file mode 100644 index 000000000000..e06966030f6d --- /dev/null +++ b/src/audio/drc/drc_hifi4.c @@ -0,0 +1,911 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin + +#include +#include +#include +#include +#include +#include +#include +#include + +#if DRC_HIFI4 + +#include + +#define ONE_Q20 1048576 /* Q_CONVERT_FLOAT(1.0f, 20) */ +#define ONE_Q21 2097152 /* Q_CONVERT_FLOAT(1.0f, 21) */ +#define ONE_Q30 1073741824 /* Q_CONVERT_FLOAT(1.0f, 30) */ +#define TWELVE_Q21 25165824 /* Q_CONVERT_FLOAT(12.0f, 21) */ +#define HALF_Q24 8388608 /* Q_CONVERT_FLOAT(0.5f, 24) */ +#define NEG_TWO_DB_Q30 852903424 /* Q_CONVERT_FLOAT(0.7943282347242815f, 30) */ +#define LSHIFT_QX31_QY20_QZ27 7 /*drc_get_lshift(31, 20, 27)*/ +#define LSHIFT_QX24_QY20_QZ24 11 /*drc_get_lshift(24, 20, 24)*/ +#define LSHIFT_QX24_QY20_QZ30 17 /*drc_get_lshift(24, 20, 30)*/ +#define LSHIFT_QX30_QY20_QZ30 11 /*drc_get_lshift(30, 20, 30)*/ +#define LSHIFT_QX30_QY30_QZ30 1 /*drc_get_lshift(30, 30, 30)*/ +#define LSHIFT_QX26_QY30_QZ27 2 /*drc_get_lshift(26, 30, 27)*/ +#define LSHIFT_QX21_QY30_QZ24 4 /*drc_get_lshift(21, 30, 24)*/ +#define LSHIFT_QX21_QY21_QZ21 10 /*drc_get_lshift(21, 21, 21)*/ +#define LSHIFT_QX30_QY16_QZ24 9 /*drc_get_lshift(31, 16, 24)*/ +#define LSHIFT_QX15_QY24_QZ15 7 /*drc_get_lshift(15, 24, 15)*/ +#define LSHIFT_QX31_QY24_QZ31 7 /*drc_get_lshift(31, 24, 31)*/ + +/* This is the knee part of the compression curve. Returns the output level + * given the input level x. + */ +static inline void set_circular_buf0(void *buf, void *buf_end) +{ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); +} + +static inline void set_circular_buf1(void *buf, void *buf_end) +{ + AE_SETCBEGIN1(buf); + AE_SETCEND1(buf_end); +} + +static int32_t knee_curveK(const struct sof_drc_params *p, int32_t x) +{ + ae_f32 gamma; /* Q5.27 */ + ae_f32 knee_exp_gamma; /* Q12.20 */ + ae_f32 knee_curve_k; /* Q8.24 */ + + /* The formula in knee_curveK is linear_threshold + + * (1 - expf(-k * (x - linear_threshold))) / k + * which simplifies to (alpha + beta * expf(gamma)) + * where alpha = linear_threshold + 1 / k + * beta = -expf(k * linear_threshold) / k + * gamma = -k * x + */ + gamma = drc_mult_lshift(x, -p->K, LSHIFT_QX31_QY20_QZ27); + knee_exp_gamma = exp_fixed(gamma); + knee_curve_k = drc_mult_lshift(p->knee_beta, knee_exp_gamma, LSHIFT_QX24_QY20_QZ24); + knee_curve_k = AE_ADD32(knee_curve_k, p->knee_alpha); + return knee_curve_k; +} + +/* Full compression curve with constant ratio after knee. Returns the ratio of + * output and input signal. + */ +static int32_t volume_gain(const struct sof_drc_params *p, int32_t x) +{ + const ae_f32 knee_threshold = AE_SLAI32S(p->knee_threshold, 7); /* Q8.24 -> Q1.31 */ + const ae_f32 linear_threshold = AE_SLAI32S(p->linear_threshold, 1); /* Q2.30 -> Q1.31 */ + ae_f32 exp_knee; /* Q12.20 */ + ae_f32 y; /* Q2.30 */ + ae_f32 tmp; + ae_f32 tmp2; + + if (x < (int32_t)knee_threshold) { + if (x < (int32_t)linear_threshold) + return ONE_Q30; + /* y = knee_curveK(x) / x */ + y = drc_mult_lshift(knee_curveK(p, x), drc_inv_fixed(x, 31, 20), + LSHIFT_QX24_QY20_QZ30); + } else { + /* Constant ratio after knee. + * log(y/y0) = s * log(x/x0) + * => y = y0 * (x/x0)^s + * => y = [y0 * (1/x0)^s] * x^s + * => y = ratio_base * x^s + * => y/x = ratio_base * x^(s - 1) + * => y/x = ratio_base * e^(log(x) * (s - 1)) + */ + tmp = AE_SRAI32R(x, 5); /* Q1.31 -> Q5.26 */ + tmp = drc_log_fixed(tmp); /* Q6.26 */ + tmp2 = AE_SUB32(p->slope, ONE_Q30); /* Q2.30 */ + exp_knee = exp_fixed(drc_mult_lshift(tmp, tmp2, LSHIFT_QX26_QY30_QZ27)); + y = drc_mult_lshift(p->ratio_base, exp_knee, LSHIFT_QX30_QY20_QZ30); + } + + return y; +} + +/* Update detector_average from the last input division. */ +void drc_update_detector_average(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + ae_f32 detector_average = state->detector_average; /* Q2.30 */ + ae_int32 abs_input_array[DRC_DIVISION_FRAMES]; /* Q1.31 */ + ae_int32 *abs_input_array_p; + int div_start, i, ch; + ae_int16 *sample16_p; /* for s16 format case */ + ae_int32 *sample32_p; /* for s24 and s32 format cases */ + ae_int32x2 sample32; + ae_int32x2 temp; + ae_int16x4 sample16; + ae_f32 gain; + ae_f32 gain_diff; + ae_f32 db_per_frame; + ae_f32 sat_release_rate; + ae_f32 tmp; + int is_release; + + /* Calculate the start index of the last input division */ + if (state->pre_delay_write_index == 0) + div_start = CONFIG_DRC_MAX_PRE_DELAY_FRAMES - DRC_DIVISION_FRAMES; + else + div_start = state->pre_delay_write_index - DRC_DIVISION_FRAMES; + + /* The max abs value across all channels for this frame */ + memset(abs_input_array, 0, DRC_DIVISION_FRAMES * sizeof(int32_t)); + if (nbyte == 2) { /* 2 bytes per sample */ + for (ch = 0; ch < nch; ch++) { + abs_input_array_p = abs_input_array; + sample16_p = (ae_int16 *)state->pre_delay_buffers[ch] + div_start; + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + AE_L16_XP(sample16, sample16_p, nbyte); + sample32 = AE_CVT32X2F16_10(sample16); + temp = AE_L32_I(abs_input_array_p, 0); + sample32 = AE_MAXABS32S(sample32, temp); + AE_S32_L_XP(sample32, abs_input_array_p, 4); + } + } + } else { /* 4 bytes per sample */ + for (ch = 0; ch < nch; ch++) { + abs_input_array_p = abs_input_array; + sample32_p = (ae_int32 *)state->pre_delay_buffers[ch] + div_start; + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + AE_L32_XP(sample32, sample32_p, nbyte); + temp = AE_L32_I(abs_input_array_p, 0); + sample32 = AE_MAXABS32S(sample32, temp); + AE_S32_L_XP(sample32, abs_input_array_p, nbyte); + } + } + } + + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + /* Compute compression amount from un-delayed signal */ + + /* Calculate shaped power on undelayed input. Put through + * shaping curve. This is linear up to the threshold, then + * enters a "knee" portion followed by the "ratio" portion. The + * transition from the threshold to the knee is smooth (1st + * derivative matched). The transition from the knee to the + * ratio portion is smooth (1st derivative matched). + */ + gain = volume_gain(p, abs_input_array[i]); /* Q2.30 */ + gain_diff = AE_SUB32(gain, detector_average); /* Q2.30 */ + is_release = ((int32_t)gain_diff > 0); + if (is_release) { + if ((int32_t)gain > NEG_TWO_DB_Q30) { + tmp = drc_mult_lshift(gain_diff, p->sat_release_rate_at_neg_two_db, + LSHIFT_QX30_QY30_QZ30); + } else { + gain = AE_SRAI32R(gain, 4); /* Q2.30 -> Q6.26 */ + db_per_frame = drc_mult_lshift(drc_lin2db_fixed(gain), + p->sat_release_frames_inv_neg, + LSHIFT_QX21_QY30_QZ24); + sat_release_rate = AE_SUB32(db2lin_fixed(db_per_frame), ONE_Q20); + tmp = drc_mult_lshift(gain_diff, sat_release_rate, + LSHIFT_QX30_QY20_QZ30); + } + detector_average = AE_ADD32(detector_average, tmp); + } else { + detector_average = gain; + } + + detector_average = AE_MIN32(detector_average, ONE_Q30); + } + + state->detector_average = detector_average; +} + +/* Updates the envelope_rate used for the next division */ +void drc_update_envelope(struct drc_state *state, const struct sof_drc_params *p) +{ + /* Deal with envelopes */ + + /* envelope_rate is the rate we slew from current compressor level to + * the desired level. The exact rate depends on if we're attacking or + * releasing and by how much. + */ + ae_f32 envelope_rate; + + /* compression_diff_db is the difference between current compression + * level and the desired level. + */ + ae_f32 compression_diff_db; + ae_f32 x, x2, x3, x4; + ae_f64 release_frames_f64; + ae_f32 release_frames; + ae_f32 db_per_frame; + ae_f32 tmp; + ae_f32 tmp2; + int32_t scaled_desired_gain; + int32_t eff_atten_diff_db; + int32_t is_releasing; + int32_t is_bad_db; + + /* Calculate desired gain */ + + /* Pre-warp so we get desired_gain after sin() warp below. */ + scaled_desired_gain = drc_asin_fixed(state->detector_average); /* Q2.30 */ + + is_releasing = scaled_desired_gain > state->compressor_gain; + is_bad_db = (state->compressor_gain == 0 || scaled_desired_gain == 0); + + tmp = AE_SRAI32R(state->compressor_gain, 4); /* Q2.30 -> Q6.26 */ + tmp2 = AE_SRAI32R(scaled_desired_gain, 4); /* Q2.30 -> Q6.26 */ + compression_diff_db = AE_SUB32(drc_lin2db_fixed(tmp), drc_lin2db_fixed(tmp2)); /* Q11.21 */ + + if (is_releasing) { + /* Release mode - compression_diff_db should be negative dB */ + state->max_attack_compression_diff_db = INT32_MIN; + + /* Fix gremlins. */ + if (is_bad_db) + compression_diff_db = -ONE_Q21; + + /* Adaptive release - higher compression (lower + * compression_diff_db) releases faster. Contain within range: + * -12 -> 0 then scale to go from 0 -> 3 + */ + x = compression_diff_db; /* Q11.21 */ + x = AE_MAX32(-TWELVE_Q21, x); + x = AE_MIN32(0, x); + /* x = 0.25f * (x + 12) */ + x = AE_SRAI32R(AE_ADD32(x, TWELVE_Q21), 2); /* Q11.21 -> Q13.19 */ + + /* Compute adaptive release curve using 4th order polynomial. + * Normal values for the polynomial coefficients would create a + * monotonically increasing function. + */ + x2 = drc_mult_lshift(x, x, LSHIFT_QX21_QY21_QZ21); /* Q11.21 */ + x3 = drc_mult_lshift(x2, x, LSHIFT_QX21_QY21_QZ21); /* Q11.21 */ + x4 = drc_mult_lshift(x2, x2, LSHIFT_QX21_QY21_QZ21); /* Q11.21 */ + + release_frames_f64 = AE_CVT48A32(p->kA); /* Q20.12 -> Q36.28 */ + release_frames_f64 = AE_SRAI64(release_frames_f64, 10); /* Q36.28 -> Q46.18 */ + AE_MULAF32R_LL(release_frames_f64, p->kB, x); /* Q20.12 * Q11.21 = Q46.18 */ + AE_MULAF32R_LL(release_frames_f64, p->kC, x2); + AE_MULAF32R_LL(release_frames_f64, p->kD, x3); + AE_MULAF32R_LL(release_frames_f64, p->kE, x4); + release_frames_f64 = AE_SLAI64S(release_frames_f64, 10); /* Q46.18 -> Q36.28 */ + release_frames = AE_ROUND32F48SSYM(release_frames_f64); /* Q36.28 -> Q20.12 */ + + /* db_per_frame = kSpacingDb / release_frames */ + db_per_frame = drc_inv_fixed(release_frames, 12, 30); /* Q2.30 */ + tmp = p->kSpacingDb << 16; /* Q16.16 */ + /* Q8.24 */ + db_per_frame = drc_mult_lshift(db_per_frame, tmp, LSHIFT_QX30_QY16_QZ24); + envelope_rate = db2lin_fixed(db_per_frame); /* Q12.20 */ + } else { + /* Attack mode - compression_diff_db should be positive dB */ + + /* Fix gremlins. */ + if (is_bad_db) + compression_diff_db = ONE_Q21; + + /* As long as we're still in attack mode, use a rate based off + * the largest compression_diff_db we've encountered so far. + */ + tmp = AE_SLAI32S(compression_diff_db, 3); /* Q11.21 -> Q8.24 */ + state->max_attack_compression_diff_db = + AE_MAX32(state->max_attack_compression_diff_db, tmp); + + eff_atten_diff_db = + MAX(HALF_Q24, state->max_attack_compression_diff_db); /* Q8.24 */ + + /* x = 0.25f / eff_atten_diff_db; + * => x = 1.0f / (eff_atten_diff_db << 2); + */ + x = drc_inv_fixed(eff_atten_diff_db, 22 /* Q8.24 << 2 */, 26); /* Q6.26 */ + envelope_rate = AE_SUB32(ONE_Q20, + drc_pow_fixed(x, p->one_over_attack_frames)); /* Q12.20 */ + } + + tmp = AE_SLAI32S(envelope_rate, 10); /* Q12.20 -> Q2.30 */ + state->envelope_rate = tmp; + state->scaled_desired_gain = scaled_desired_gain; +} + +/* Calculate compress_gain from the envelope and apply total_gain to compress + * the next output division. + */ +void drc_compress_output(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + const int count = DRC_DIVISION_FRAMES >> 2; + ae_f32 x[4]; /* Q2.30 */ + ae_f32 c, base, r, r2, r4; /* Q2.30 */ + ae_f32 post_warp_compressor_gain; + ae_f32 total_gain; + int i, j, ch; + int inc = state->pre_delay_read_index; + int16_t *sample16_p; /* for s16 format case */ + int32_t *sample32_p; /* for s24 and s32 format cases */ + int32_t sample; + int is_2byte = (nbyte == 2); /* otherwise is 4-bytes */ + ae_f32 tmp; + ae_f64 tmp64; + ae_f32 master_linear_gain = p->master_linear_gain; + + /* Exponential approach to desired gain. */ + if (state->envelope_rate < ONE_Q30) { + /* Attack - reduce gain to desired. */ + c = AE_SUB32(state->compressor_gain, state->scaled_desired_gain); + base = state->scaled_desired_gain; + r = AE_SUB32(ONE_Q30, state->envelope_rate); + x[0] = drc_mult_lshift(c, r, LSHIFT_QX30_QY30_QZ30); + for (j = 1; j < 4; j++) + x[j] = drc_mult_lshift(x[j - 1], r, LSHIFT_QX30_QY30_QZ30); + r2 = drc_mult_lshift(r, r, LSHIFT_QX30_QY30_QZ30); + r4 = drc_mult_lshift(r2, r2, LSHIFT_QX30_QY30_QZ30); + + i = 0; + if (is_2byte) { /* 2 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + tmp = AE_ADD32(x[j], base); + post_warp_compressor_gain = drc_sin_fixed(tmp); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + tmp64 = AE_MULF32R_LL(master_linear_gain, + post_warp_compressor_gain); + total_gain = AE_ROUND32F48SSYM(tmp64); /* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + + inc; + sample = (int32_t)*sample16_p; + sample = drc_mult_lshift(sample, total_gain, + LSHIFT_QX15_QY24_QZ15); + *sample16_p = sat_int16(sample); + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) + x[j] = drc_mult_lshift(x[j], r4, LSHIFT_QX30_QY30_QZ30); + } + } else { /* 4 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + tmp = AE_ADD32(x[j], base); + post_warp_compressor_gain = drc_sin_fixed(tmp); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + tmp64 = AE_MULF32R_LL(master_linear_gain, + post_warp_compressor_gain); + total_gain = AE_ROUND32F48SSYM(tmp64);/* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + + inc; + sample = *sample32_p; + sample = drc_mult_lshift(sample, total_gain, + LSHIFT_QX31_QY24_QZ31); + *sample32_p = sample; + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) + x[j] = drc_mult_lshift(x[j], r4, LSHIFT_QX30_QY30_QZ30); + } + } + + tmp = AE_ADD32(x[3], base); + state->compressor_gain = tmp; + } else { + /* Release - exponentially increase gain to 1.0 */ + c = state->compressor_gain; + r = state->envelope_rate; + x[0] = drc_mult_lshift(c, r, LSHIFT_QX30_QY30_QZ30); + for (j = 1; j < 4; j++) + x[j] = drc_mult_lshift(x[j - 1], r, LSHIFT_QX30_QY30_QZ30); + r2 = drc_mult_lshift(r, r, LSHIFT_QX30_QY30_QZ30); + r4 = drc_mult_lshift(r2, r2, LSHIFT_QX30_QY30_QZ30); + + i = 0; + if (is_2byte) { /* 2 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = drc_sin_fixed(x[j]); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + tmp64 = AE_MULF32R_LL(master_linear_gain, + post_warp_compressor_gain); + total_gain = AE_ROUND32F48SSYM(tmp64);/* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + + inc; + sample = (int32_t)*sample16_p; + sample = drc_mult_lshift(sample, total_gain, + LSHIFT_QX15_QY24_QZ15); + *sample16_p = sat_int16(sample); + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) { + tmp = drc_mult_lshift(x[j], r4, LSHIFT_QX30_QY30_QZ30); + x[j] = AE_MIN32(ONE_Q30, tmp); + } + } + } else { /* 4 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = drc_sin_fixed(x[j]); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + tmp64 = AE_MULF32R_LL(master_linear_gain, + post_warp_compressor_gain); + total_gain = AE_ROUND32F48SSYM(tmp64);/* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + + inc; + sample = *sample32_p; + sample = drc_mult_lshift(sample, total_gain, + LSHIFT_QX31_QY24_QZ31); + *sample32_p = sample; + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) { + tmp = drc_mult_lshift(x[j], r4, LSHIFT_QX30_QY30_QZ30); + x[j] = AE_MIN32(ONE_Q30, tmp); + } + } + } + + state->compressor_gain = x[3]; + } +} + +/* After one complete division of samples have been received (and one division of + * samples have been output), we calculate shaped power average + * (detector_average) from the input division, update envelope parameters from + * detector_average, then prepare the next output division by applying the + * envelope to compress the samples. + */ +static void drc_process_one_division(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + drc_update_detector_average(state, p, nbyte, nch); + drc_update_envelope(state, p); + drc_compress_output(state, p, nbyte, nch); +} + +void drc_default_pass(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, uint32_t frames) +{ + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); +} + +static inline void drc_pre_delay_index_inc(int *idx, int increment) +{ + *idx = (*idx + increment) & DRC_MAX_PRE_DELAY_FRAMES_MASK; +} + +#if CONFIG_FORMAT_S16LE +static void drc_delay_input_sample_s16(struct drc_state *state, + const struct audio_stream *source, + struct audio_stream *sink, + int16_t **x, int16_t **y, int samples) +{ + ae_int16 *x1; + ae_int16 *y1; + ae_int16 *pd; + ae_int16 *pd_r; + ae_int16 *pd_w; + int nbuf, npcm, nfrm; + int ch; + int i; + ae_int16 *x0 = (ae_int16 *)*x; + ae_int16 *y0 = (ae_int16 *)*y; + int remaining_samples = samples; + int nch = audio_stream_get_channels(source); + const int sample_inc = nch * sizeof(int16_t); + const int delay_inc = sizeof(int16_t); + ae_int16x4 sample; + + while (remaining_samples) { + nbuf = audio_stream_samples_without_wrap_s16(source, x0); + npcm = MIN(remaining_samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s16(sink, y0); + npcm = MIN(npcm, nbuf); + nfrm = npcm / nch; + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int16 *)state->pre_delay_buffers[ch]; + set_circular_buf0(pd, pd + CONFIG_DRC_MAX_PRE_DELAY_FRAMES); + x1 = x0 + ch; + y1 = y0 + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + for (i = 0; i < nfrm; i++) { + AE_L16_XP(sample, x1, sample_inc); + AE_S16_0_XC(sample, pd_w, delay_inc); + /*pop sample from delay buffer and store in output buffer*/ + AE_L16_XC(sample, pd_r, delay_inc); + AE_S16_0_XP(sample, y1, sample_inc); + } + } + remaining_samples -= npcm; + x0 = audio_stream_wrap(source, x0 + npcm); + y0 = audio_stream_wrap(sink, y0 + npcm); + drc_pre_delay_index_inc(&state->pre_delay_write_index, nfrm); + drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); + } + + *x = x0; + *y = y0; +} + +static void drc_s16_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + int samples = frames * nch; + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment; + ae_int16 *pd; + ae_int16 *pd_r; + ae_int16 *pd_w; + ae_int16 *x1; + ae_int16 *y1; + int i, ch; + ae_int16x4 sample; + const int sample_inc = nch * sizeof(ae_int16); + const int delay_inc = sizeof(ae_int16); + + if (!p->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. + */ + drc_delay_input_sample_s16(state, source, sink, &x, &y, samples); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int16_t), nch); + state->processed = 1; + } + + set_circular_buf0(source->addr, source->end_addr); + set_circular_buf1(sink->addr, sink->end_addr); + + while (frames) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment = MIN(frames, fragment); + + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int16 *)state->pre_delay_buffers[ch]; + x1 = (ae_int16 *)x + ch; + y1 = (ae_int16 *)y + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + + /* don't need to check the boundary of pre-delay because the + * state->pre_delay_write_index + frames will always be aligned with + * 32(DRC_DIVISION_FRAMES), and the pre-delay buffer size (a multiple + * of CONFIG_DRC_MAX_PRE_DELAY_FRAMES) will always be the multiple of + * DRC_DIVISION_FRAMES + */ + for (i = 0; i < fragment; i++) { + AE_L16_XC(sample, x1, sample_inc); + AE_S16_0_XP(sample, pd_w, delay_inc); + /*pop sample from delay buffer and store in output buffer*/ + AE_L16_XP(sample, pd_r, delay_inc); + AE_S16_0_XC1(sample, y1, sample_inc); + } + } + drc_pre_delay_index_inc(&state->pre_delay_write_index, fragment); + drc_pre_delay_index_inc(&state->pre_delay_read_index, fragment); + x = audio_stream_wrap(source, x + fragment * nch); + y = audio_stream_wrap(sink, y + fragment * nch); + frames -= fragment; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int16_t), nch); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +static void drc_delay_input_sample_s32(struct drc_state *state, + const struct audio_stream *source, + struct audio_stream *sink, + int32_t **x, int32_t **y, int samples) +{ + ae_int32 *x1; + ae_int32 *y1; + ae_int32 *pd_r; + ae_int32 *pd_w; + ae_int32 *pd; + int nbuf, npcm, nfrm; + int ch; + int i; + ae_int32 *x0 = (ae_int32 *)*x; + ae_int32 *y0 = (ae_int32 *)*y; + ae_int32x2 sample; + + int remaining_samples = samples; + int nch = audio_stream_get_channels(source); + const int sample_inc = nch * sizeof(int32_t); + const int delay_inc = sizeof(int32_t); + + while (remaining_samples) { + nbuf = audio_stream_samples_without_wrap_s32(source, x0); + npcm = MIN(remaining_samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s32(sink, y0); + npcm = MIN(npcm, nbuf); + nfrm = npcm / nch; + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int32 *)state->pre_delay_buffers[ch]; + set_circular_buf0(pd, pd + CONFIG_DRC_MAX_PRE_DELAY_FRAMES); + x1 = x0 + ch; + y1 = y0 + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + + for (i = 0; i < nfrm; i++) { + /*store the input sample to delay buffer*/ + AE_L32_XP(sample, x1, sample_inc); + AE_S32_L_XC(sample, pd_w, delay_inc); + + /*pop sample from delay buffer and store in output buffer*/ + AE_L32_XC(sample, pd_r, delay_inc); + AE_S32_L_XP(sample, y1, sample_inc); + } + } + remaining_samples -= npcm; + x0 = audio_stream_wrap(source, x0 + npcm); + y0 = audio_stream_wrap(sink, y0 + npcm); + drc_pre_delay_index_inc(&state->pre_delay_write_index, nfrm); + drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); + } + + *x = x0; + *y = y0; +} +#endif + +#if CONFIG_FORMAT_S24LE + +static void drc_s24_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + int samples = frames * nch; + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment; + ae_int32 *pd; + ae_int32 *pd_r; + ae_int32 *pd_w; + ae_int32 *x1; + ae_int32 *y1; + int i, ch; + ae_int32x2 sample; + const int sample_inc = nch * sizeof(int32_t); + const int delay_inc = sizeof(int32_t); + + if (!p->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. Note: use 32 bit delay function. + */ + drc_delay_input_sample_s32(state, source, sink, &x, &y, samples); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int32_t), nch); + state->processed = 1; + } + + set_circular_buf0(source->addr, source->end_addr); + set_circular_buf1(sink->addr, sink->end_addr); + + while (frames) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment = MIN(frames, fragment); + + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int32 *)state->pre_delay_buffers[ch]; + x1 = (ae_int32 *)x + ch; + y1 = (ae_int32 *)y + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + + /* don't need to check the boundary of pre-delay because the + * state->pre_delay_write_index + frames will always be aligned with + * 32(DRC_DIVISION_FRAMES), and the pre-delay buffer size (a multiple + * of CONFIG_DRC_MAX_PRE_DELAY_FRAMES) will always be the multiple of + * DRC_DIVISION_FRAMES + */ + for (i = 0; i < fragment; i++) { + /*store the input sample to delay buffer*/ + AE_L32_XC(sample, x1, sample_inc); + sample = AE_SLAI32(sample, 8); /*Q9.23 -> Q1.31*/ + AE_S32_L_XP(sample, pd_w, delay_inc); + + /*pop sample from delay buffer and store in output buffer*/ + AE_L32_XP(sample, pd_r, delay_inc); + sample = AE_SRAI32R(sample, 8); + sample = AE_SLAA32S(sample, 8); + sample = AE_SRAI32(sample, 8); + + AE_S32_L_XC1(sample, y1, sample_inc); + } + } + drc_pre_delay_index_inc(&state->pre_delay_write_index, fragment); + drc_pre_delay_index_inc(&state->pre_delay_read_index, fragment); + x = audio_stream_wrap(source, x + fragment * nch); + y = audio_stream_wrap(sink, y + fragment * nch); + frames -= fragment; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int32_t), nch); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void drc_s32_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment; + ae_int32 *pd; + ae_int32 *pd_r; + ae_int32 *pd_w; + ae_int32 *x1; + ae_int32 *y1; + int i, ch; + ae_int32x2 sample; + const int sample_inc = nch * sizeof(int32_t); + const int delay_inc = sizeof(int32_t); + + if (!p->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. + */ + drc_delay_input_sample_s32(state, source, sink, &x, &y, frames * nch); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int32_t), nch); + state->processed = 1; + } + + set_circular_buf0(source->addr, source->end_addr); + set_circular_buf1(sink->addr, sink->end_addr); + + while (frames) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment = MIN(frames, fragment); + + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int32 *)state->pre_delay_buffers[ch]; + x1 = (ae_int32 *)x + ch; + y1 = (ae_int32 *)y + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + + /* don't need to check the boundary of pre-delay because the + * state->pre_delay_write_index + frames will always be aligned with + * 32(DRC_DIVISION_FRAMES), and the pre-delay buffer size (a multiple + * of CONFIG_DRC_MAX_PRE_DELAY_FRAMES) will always be the multiple of + * DRC_DIVISION_FRAMES + */ + for (i = 0; i < fragment; i++) { + /*store the input sample to delay buffer*/ + AE_L32_XC(sample, x1, sample_inc); + AE_S32_L_XP(sample, pd_w, delay_inc); + + /*pop sample from delay buffer and store in output buffer*/ + AE_L32_XP(sample, pd_r, delay_inc); + AE_S32_L_XC1(sample, y1, sample_inc); + } + } + drc_pre_delay_index_inc(&state->pre_delay_write_index, fragment); + drc_pre_delay_index_inc(&state->pre_delay_read_index, fragment); + x = audio_stream_wrap(source, x + fragment * nch); + y = audio_stream_wrap(sink, y + fragment * nch); + frames -= fragment; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int32_t), nch); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct drc_proc_fnmap drc_proc_fnmap[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, drc_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, drc_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, drc_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t drc_proc_fncount = ARRAY_SIZE(drc_proc_fnmap); + +#endif /* DRC_HIFI4 */ diff --git a/src/audio/drc/drc_math_hifi3.c b/src/audio/drc/drc_math_hifi3.c index 1b970a231545..0849e3a443ec 100644 --- a/src/audio/drc/drc_math_hifi3.c +++ b/src/audio/drc/drc_math_hifi3.c @@ -7,7 +7,7 @@ #include #include -#if DRC_HIFI3 +#if DRC_HIFI3 || DRC_HIFI4 #include diff --git a/src/include/sof/audio/drc/drc_math.h b/src/include/sof/audio/drc/drc_math.h index 92b6242556df..d2c4965fd3e1 100644 --- a/src/include/sof/audio/drc/drc_math.h +++ b/src/include/sof/audio/drc/drc_math.h @@ -17,7 +17,7 @@ /* Unmark this define to use cordic arc sine implementation. */ /* #define DRC_USE_CORDIC_ASIN */ -#if DRC_HIFI3 +#if DRC_HIFI3 || DRC_HIFI4 #include diff --git a/src/include/sof/audio/drc/drc_plat_conf.h b/src/include/sof/audio/drc/drc_plat_conf.h index 977a83a68be7..8bdab58bb308 100644 --- a/src/include/sof/audio/drc/drc_plat_conf.h +++ b/src/include/sof/audio/drc/drc_plat_conf.h @@ -20,23 +20,31 @@ #if DRC_AUTOARCH == 0 #define DRC_GENERIC 1 #define DRC_HIFI3 0 +#define DRC_HIFI4 0 #endif /* Select optimized code variant when xt-xcc compiler is used */ #if DRC_AUTOARCH == 1 #if defined __XCC__ #include -#if XCHAL_HAVE_HIFI3 == 1 +#if XCHAL_HAVE_HIFI4 == 1 +#define DRC_GENERIC 0 +#define DRC_HIFI3 0 +#define DRC_HIFI4 1 +#elif XCHAL_HAVE_HIFI3 == 1 #define DRC_GENERIC 0 #define DRC_HIFI3 1 +#define DRC_HIFI4 0 #else #define DRC_GENERIC 1 #define DRC_HIFI3 0 +#define DRC_HIFI4 0 #endif /* XCHAL_HAVE_HIFI3 */ #else /* GCC */ #define DRC_GENERIC 1 #define DRC_HIFI3 0 +#define DRC_HIFI4 0 #endif /* __XCC__ */ #endif /* DRC_AUTOARCH */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 563dc6b14622..f9e1f3c40e00 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -686,6 +686,7 @@ zephyr_library_sources_ifdef(CONFIG_COMP_DRC ${SOF_AUDIO_PATH}/drc/drc_generic.c ${SOF_AUDIO_PATH}/drc/drc_math_generic.c ${SOF_AUDIO_PATH}/drc/drc_hifi3.c + ${SOF_AUDIO_PATH}/drc/drc_hifi4.c ${SOF_AUDIO_PATH}/drc/drc_math_hifi3.c ) From 383d17a19e25f804d2ba37b6b621131918544e6a Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Wed, 8 Nov 2023 11:18:00 +0800 Subject: [PATCH 18/48] copier: add support for windows driver Windows driver always set sample type of MSB for 24/32 format but SOF FW supports 24/32 LSB type for non-copier modules. So FW will convert the input MSB 24/32 to LSB 24/32 and process it and convert it back to MSB 24/32 when exiting gtw. Signed-off-by: Rander Wang Signed-off-by: Damian Nikodem --- src/audio/copier/copier_generic.c | 43 ++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c index 8c3a3278c7d1..37d89430d38f 100644 --- a/src/audio/copier/copier_generic.c +++ b/src/audio/copier/copier_generic.c @@ -274,10 +274,45 @@ pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt, audio_stream_fmt_conversion(out_fmt->depth, out_fmt->valid_bit_depth, &out, &out_valid, out_fmt->s_type); - if (in_fmt->s_type == IPC4_TYPE_MSB_INTEGER && in_valid == SOF_IPC_FRAME_S24_4LE) - in_valid = SOF_IPC_FRAME_S24_4LE_MSB; - if (out_fmt->s_type == IPC4_TYPE_MSB_INTEGER && out_valid == SOF_IPC_FRAME_S24_4LE) - out_valid = SOF_IPC_FRAME_S24_4LE_MSB; + /* use MSB sample type to select conversion function if the data is enter or exit dsp. + * In playback case, host input and dai output and in capture case, host output and + * dai input. + */ + if (in_fmt->s_type == IPC4_TYPE_MSB_INTEGER && in_valid == SOF_IPC_FRAME_S24_4LE) { + switch (type) { + case ipc4_gtw_host: + if (dir == ipc4_playback) + in_valid = SOF_IPC_FRAME_S24_4LE_MSB; + break; + case ipc4_gtw_alh: + case ipc4_gtw_link: + case ipc4_gtw_ssp: + case ipc4_gtw_dmic: + if (dir == ipc4_capture) + in_valid = SOF_IPC_FRAME_S24_4LE_MSB; + break; + default: + break; + } + } + + if (out_fmt->s_type == IPC4_TYPE_MSB_INTEGER && out_valid == SOF_IPC_FRAME_S24_4LE) { + switch (type) { + case ipc4_gtw_host: + if (dir == ipc4_capture) + out_valid = SOF_IPC_FRAME_S24_4LE_MSB; + break; + case ipc4_gtw_alh: + case ipc4_gtw_link: + case ipc4_gtw_ssp: + case ipc4_gtw_dmic: + if (dir == ipc4_playback) + out_valid = SOF_IPC_FRAME_S24_4LE_MSB; + break; + default: + break; + } + } /* check container & sample size */ if (use_no_container_convert_function(in, in_valid, out, out_valid)) From 39173087d9818df446d3f20715b9a52d99b831df Mon Sep 17 00:00:00 2001 From: "barry.jan" Date: Mon, 6 Nov 2023 18:59:40 +0800 Subject: [PATCH 19/48] waves: store config blob in a cache in waves.c Store/apply config blob in a cache to avoid that cfg.data will be released after prepare. Signed-off-by: barry.jan --- src/audio/module_adapter/module/waves/waves.c | 193 ++++++++++-------- 1 file changed, 106 insertions(+), 87 deletions(-) diff --git a/src/audio/module_adapter/module/waves/waves.c b/src/audio/module_adapter/module/waves/waves.c index ab178b022eb9..44a7545149a5 100644 --- a/src/audio/module_adapter/module/waves/waves.c +++ b/src/audio/module_adapter/module/waves/waves.c @@ -41,7 +41,8 @@ struct waves_codec_data { uint32_t response_max_bytes; uint32_t request_max_bytes; void *response; - struct module_config setup_cfg; + uint32_t config_blob_size; + void *config_blob; }; enum waves_codec_params { @@ -456,6 +457,51 @@ static int waves_effect_revision(struct processing_module *mod) return 0; } +/* cache config blob*/ +static int waves_effect_save_config_blob_to_cache(struct processing_module *mod, + void *data, uint32_t size) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + + comp_info(dev, "waves_effect_save_config_blob_to_cache() start"); + + /* release old cached config blob*/ + if (waves_codec->config_blob && size != waves_codec->config_blob_size) { + comp_info(dev, "waves_effect_save_config_blob_to_cache() release blob"); + module_free_memory(mod, waves_codec->config_blob); + waves_codec->config_blob = NULL; + waves_codec->config_blob_size = 0; + } + + if (!waves_codec->config_blob) { + waves_codec->config_blob = module_allocate_memory(mod, size, 16); + if (!waves_codec->config_blob) { + comp_err(dev, + "waves_effect_save_config_blob_to_cache() failed to allocate %d bytes for config blob", + size); + return -ENOMEM; + } + waves_codec->config_blob_size = size; + } + + int ret = memcpy_s(waves_codec->config_blob, waves_codec->config_blob_size, + data, size); + if (ret) { + comp_err(dev, + "waves_effect_save_config_blob_to_cache(): failed to copy config blob %d", + ret); + module_free_memory(mod, waves_codec->config_blob); + waves_codec->config_blob = NULL; + waves_codec->config_blob_size = 0; + return ret; + } + + comp_dbg(dev, "waves_effect_save_config_blob_to_cache() done"); + return 0; +} + /* apply MaxxEffect message */ static int waves_effect_message(struct processing_module *mod, void *data, uint32_t size) { @@ -492,37 +538,62 @@ static int waves_effect_message(struct processing_module *mod, void *data, uint3 return 0; } -/* apply codec config */ -static int waves_effect_config(struct processing_module *mod) +/* apply config blob */ +static int waves_effect_apply_config_blob_from_cache(struct processing_module *mod) { struct comp_dev *dev = mod->dev; struct module_data *codec = &mod->priv; struct waves_codec_data *waves_codec = codec->private; + + comp_info(dev, "waves_effect_apply_config_blob_from_cache()"); + + if (waves_codec->config_blob) { + return waves_effect_message(mod, waves_codec->config_blob, + waves_codec->config_blob_size); + } + return 0; +} + +static int waves_effect_handle_param_message(struct processing_module *mod, + void *data, uint32_t size) +{ + int ret = waves_effect_save_config_blob_to_cache(mod, data, size); + + if (!ret) + ret = waves_effect_apply_config_blob_from_cache(mod); + + return ret; +} + +/* apply codec config */ +static int waves_effect_apply_config(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; struct module_param *param; struct module_config *cfg; uint32_t index; uint32_t param_number = 0; int ret = 0; - comp_info(dev, "waves_codec_configure() start"); + comp_info(dev, "waves_effect_apply_config() start"); cfg = &codec->cfg; - /* use setup config if no runtime config available */ - if (!cfg->avail) - cfg = &waves_codec->setup_cfg; - - comp_info(dev, "waves_codec_configure() config %p, size %d, avail %d", + comp_info(dev, "waves_effect_apply_config() config %p, size %d, avail %d", cfg->data, cfg->size, cfg->avail); - if (!cfg->avail || !cfg->size) { - comp_err(dev, "waves_codec_configure() no config, avail %d, size %d", - cfg->avail, cfg->size); - return -EINVAL; + if (!cfg->data) { + ret = waves_effect_apply_config_blob_from_cache(mod); + if (ret) { + comp_err(dev, "waves_effect_apply_config() error %x: apply cache fail", + ret); + return ret; + } } if (cfg->size > MAX_CONFIG_SIZE_BYTES) { - comp_err(dev, "waves_codec_configure() provided config is too big, size %d", + comp_err(dev, "waves_effect_apply_config() provided config is too big, size %d", cfg->size); return -EINVAL; } @@ -536,15 +607,15 @@ static int waves_effect_config(struct processing_module *mod) param = (struct module_param *)((char *)cfg->data + index); param_data_size = param->size - sizeof(param->size) - sizeof(param->id); - comp_info(dev, "waves_codec_configure() param num %d id %d size %d", + comp_info(dev, "waves_effect_apply_config() param num %d id %d size %d", param_number, param->id, param->size); switch (param->id) { case PARAM_NOP: - comp_info(dev, "waves_codec_configure() NOP"); + comp_info(dev, "waves_effect_apply_config() NOP"); break; case PARAM_MESSAGE: - ret = waves_effect_message(mod, param->data, param_data_size); + ret = waves_effect_handle_param_message(mod, param->data, param_data_size); break; case PARAM_REVISION: ret = waves_effect_revision(mod); @@ -557,28 +628,12 @@ static int waves_effect_config(struct processing_module *mod) index += param->size; } - if (ret) - comp_err(dev, "waves_codec_configure() failed %d", ret); - - comp_dbg(dev, "waves_codec_configure() done"); - return ret; -} - -/* apply setup config */ -static int waves_effect_setup_config(struct processing_module *mod) -{ - struct comp_dev *dev = mod->dev; - int ret; - - comp_dbg(dev, "waves_effect_setup_config() start"); - - ret = waves_effect_config(mod); - if (ret < 0) { - comp_err(dev, "waves_effect_setup_config(): fail to apply config"); + if (ret) { + comp_err(dev, "waves_effect_apply_config() failed %d", ret); return ret; } - comp_dbg(dev, "waves_effect_setup_config() done"); + comp_dbg(dev, "waves_effect_apply_config() done"); return 0; } @@ -598,9 +653,7 @@ static int waves_codec_init(struct processing_module *mod) sizeof(struct waves_codec_data)); ret = -ENOMEM; } else { - memset(waves_codec, 0, sizeof(struct waves_codec_data)); codec->private = waves_codec; - ret = waves_effect_allocate(mod); if (ret) { module_free_memory(mod, waves_codec); @@ -612,32 +665,6 @@ static int waves_codec_init(struct processing_module *mod) comp_err(dev, "waves_codec_init() failed %d", ret); return ret; } - waves_codec->setup_cfg.avail = false; - - /* copy the setup config only for the first init */ - if (codec->state == MODULE_DISABLED && codec->cfg.avail) { - struct module_config *setup_cfg = &waves_codec->setup_cfg; - - /* allocate memory for set up config */ - setup_cfg->data = module_allocate_memory(mod, codec->cfg.size, 16); - if (!setup_cfg->data) { - comp_err(dev, "waves_codec_init(): failed to alloc setup config"); - module_free_memory(mod, waves_codec); - return -ENOMEM; - } - - /* copy the setup config */ - setup_cfg->size = codec->cfg.size; - ret = memcpy_s(setup_cfg->data, setup_cfg->size, - codec->cfg.init_data, setup_cfg->size); - if (ret) { - comp_err(dev, "waves_codec_init(): failed to copy setup config %d", ret); - module_free_memory(mod, setup_cfg->data); - module_free_memory(mod, waves_codec); - return ret; - } - setup_cfg->avail = true; - } ret = MaxxEffect_GetMessageMaxSize(waves_codec->effect, &waves_codec->request_max_bytes, &waves_codec->response_max_bytes); @@ -669,20 +696,26 @@ static int waves_codec_prepare(struct processing_module *mod, comp_dbg(dev, "waves_codec_prepare() start"); ret = waves_effect_check(dev); + if (ret) + goto error; - if (!ret) - ret = waves_effect_init(mod); - - if (!ret) - ret = waves_effect_buffers(mod); + ret = waves_effect_init(mod); + if (ret) + goto error; - if (!ret) - ret = waves_effect_setup_config(mod); + ret = waves_effect_buffers(mod); + if (ret) + goto error; + ret = waves_effect_apply_config(mod); if (ret) - comp_err(dev, "waves_codec_prepare() failed %d", ret); + goto error; comp_dbg(dev, "waves_codec_prepare() done"); + return 0; + +error: + comp_err(dev, "waves_codec_prepare() failed %d", ret); return ret; } @@ -774,20 +807,6 @@ waves_codec_process(struct processing_module *mod, return ret; } -static int waves_codec_apply_config(struct processing_module *mod) -{ - int ret; - struct comp_dev *dev = mod->dev; - - comp_dbg(dev, "waves_codec_apply_config() start"); - ret = waves_effect_config(mod); - if (ret) - comp_err(dev, "waves_codec_apply_config() failed %d", ret); - - comp_dbg(dev, "waves_codec_apply_config() done"); - return ret; -} - static int waves_codec_reset(struct processing_module *mod) { MaxxStatus_t status; @@ -845,7 +864,7 @@ waves_codec_set_configuration(struct processing_module *mod, uint32_t config_id, return 0; /* whole configuration received, apply it now */ - ret = waves_codec_apply_config(mod); + ret = waves_effect_apply_config(mod); if (ret) { comp_err(dev, "waves_codec_set_configuration(): error %x: runtime config apply failed", ret); From 5c0f8bdf6aea4fdaa904a90af827217bfe9da7f0 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 24 Nov 2023 19:09:09 +0200 Subject: [PATCH 20/48] versions.json: set version to 2.8.99 Open tree for 2.9 development now that stable-v2.8 is branched out. Signed-off-by: Kai Vehmanen --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index 0b87aa1393c9..03aede92a201 100644 --- a/versions.json +++ b/versions.json @@ -1,7 +1,7 @@ { "SOF": { "MAJOR": "2", - "MINOR": "7", + "MINOR": "8", "MICRO": "99" } } From 98cc6892329c369a6ccfd651a804b9196e441855 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Wed, 8 Nov 2023 15:15:02 +0100 Subject: [PATCH 21/48] module: module_adapter: lmdk: Improved module type detection Defined API version used by a FDK modules. Created the DECLARE_LOADABLE_MODULE_API_VERSION macro with which the loadable modules can easily declare the version of used API. Improved module type recognition. Now the type is recognized based on the value of the format field instead of the API version. Added check for compatibility of API version used by module. Signed-off-by: Adrian Warecki --- lmdk/libraries/dummy/dummy_mtl.toml | 1 - src/audio/module_adapter/module/modules.c | 16 +++++++++----- src/include/module/module/api_ver.h | 21 +++++++++++++----- .../audio/module_adapter/iadk/api_version.h | 22 +++++++++++++++++++ 4 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 src/include/sof/audio/module_adapter/iadk/api_version.h diff --git a/lmdk/libraries/dummy/dummy_mtl.toml b/lmdk/libraries/dummy/dummy_mtl.toml index 7f984d2a2382..3094e10f3396 100644 --- a/lmdk/libraries/dummy/dummy_mtl.toml +++ b/lmdk/libraries/dummy/dummy_mtl.toml @@ -44,7 +44,6 @@ length = "0x0" # calculated by rimage [signed_pkg] name = "ADSP" -partition_usage = "0x23" [[signed_pkg.module]] name = "ADSP.met" diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 90634c2253ad..1f7ee82b6a42 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -101,17 +102,22 @@ static int modules_init(struct processing_module *mod) void *mod_adp; - /* Check if module is FDK*/ - if (mod_buildinfo->api_version_number.fields.major < SOF_MODULE_API_MAJOR_VERSION) { + /* Check if module is FDK */ + if (mod_buildinfo->format == IADK_MODULE_API_BUILD_INFO_FORMAT && + mod_buildinfo->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { mod_adp = system_agent_start(md->module_entry_point, module_id, instance_id, 0, log_handle, &mod_cfg); - } else { - /* If not start agent for sof loadable */ + } else + /* Check if module is native */ + if (mod_buildinfo->format == SOF_MODULE_API_BUILD_INFO_FORMAT && + mod_buildinfo->api_version_number.full == SOF_MODULE_API_CURRENT_VERSION) { + /* If start agent for sof loadable */ mod->is_native_sof = true; mod_adp = native_system_agent_start(mod->sys_service, md->module_entry_point, module_id, instance_id, 0, log_handle, &mod_cfg); - } + } else + return -ENOEXEC; md->module_adapter = mod_adp; diff --git a/src/include/module/module/api_ver.h b/src/include/module/module/api_ver.h index a315400df4f2..680745f8c323 100644 --- a/src/include/module/module/api_ver.h +++ b/src/include/module/module/api_ver.h @@ -10,15 +10,21 @@ #include -#define ADSP_BUILD_INFO_FORMAT 0 +#define MODULE_API_VERSION_ENCODE(a, b, c) \ + (((0x3FF & (a)) << 20) | ((0x3FF & (b)) << 10) | (0x3FF & (c))) + +#define SOF_MODULE_API_BUILD_INFO_FORMAT 0x80000000 /* * Api version 5.0.0 for sof loadable modules */ -#define SOF_MODULE_API_MAJOR_VERSION 5 -#define SOF_MODULE_API_MIDDLE_VERSION 0 -#define SOF_MODULE_API_MINOR_VERSION 0 +#define SOF_MODULE_API_MAJOR_VERSION 5 +#define SOF_MODULE_API_MIDDLE_VERSION 0 +#define SOF_MODULE_API_MINOR_VERSION 0 + +#define SOF_MODULE_API_CURRENT_VERSION MODULE_API_VERSION_ENCODE(SOF_MODULE_API_MAJOR_VERSION, \ + SOF_MODULE_API_MIDDLE_VERSION, SOF_MODULE_API_MINOR_VERSION) union sof_module_api_version { uint32_t full; @@ -30,9 +36,14 @@ union sof_module_api_version { } fields; }; -struct sof_module_api_build_info{ +struct sof_module_api_build_info { uint32_t format; union sof_module_api_version api_version_number; }; +#define DECLARE_LOADABLE_MODULE_API_VERSION(name) \ +struct sof_module_api_build_info name ## _build_info __attribute__((section(".buildinfo"))) = { \ + SOF_MODULE_API_BUILD_INFO_FORMAT, SOF_MODULE_API_CURRENT_VERSION \ +} + #endif /* __MODULE_MODULE_API_VER_H__ */ diff --git a/src/include/sof/audio/module_adapter/iadk/api_version.h b/src/include/sof/audio/module_adapter/iadk/api_version.h new file mode 100644 index 000000000000..bd05e49d7239 --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/api_version.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki + */ + +#ifndef __MODULE_ADAPTER_IADK_API_VERSION_H__ +#define __MODULE_ADAPTER_IADK_API_VERSION_H__ + +#include + +#define IADK_MODULE_API_BUILD_INFO_FORMAT 0 + +#define IADK_MODULE_API_MAJOR_VERSION 4 +#define IADK_MODULE_API_MIDDLE_VERSION 5 +#define IADK_MODULE_API_MINOR_VERSION 0 + +#define IADK_MODULE_API_CURRENT_VERSION MODULE_API_VERSION_ENCODE(IADK_MODULE_API_MAJOR_VERSION, \ + IADK_MODULE_API_MIDDLE_VERSION, IADK_MODULE_API_MINOR_VERSION) + +#endif /* __MODULE_ADAPTER_IADK_API_VERSION_H__ */ From f1aaca8b85bd5a93b675baf4aabac716a19a7ee8 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Mon, 27 Nov 2023 16:06:30 +0100 Subject: [PATCH 22/48] lmdk: build: Add missing -l parameter to rimage Added missing -l parameter in rimage command line to indicate signing of a loadable module. Signed-off-by: Adrian Warecki --- lmdk/cmake/build.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lmdk/cmake/build.cmake b/lmdk/cmake/build.cmake index 8412bf313c05..047a085257f8 100644 --- a/lmdk/cmake/build.cmake +++ b/lmdk/cmake/build.cmake @@ -85,6 +85,6 @@ find_program(RIMAGE_COMMAND NAMES rimage add_custom_target(${PROJECT_NAME}_target ALL DEPENDS ${RIMAGE_MODULES_LIST} - COMMAND ${RIMAGE_COMMAND} -k ${SIGNING_KEY} -f 2.0.0 -b 1 -o ${RIMAGE_OUTPUT_FILE} -c ${TOML} -e ${RIMAGE_MODULES_LIST} + COMMAND ${RIMAGE_COMMAND} -l -k ${SIGNING_KEY} -f 2.0.0 -b 1 -o ${RIMAGE_OUTPUT_FILE} -c ${TOML} -e ${RIMAGE_MODULES_LIST} COMMAND ${CMAKE_COMMAND} -E cat ${RIMAGE_OUTPUT_FILE}.xman ${RIMAGE_OUTPUT_FILE} > ${OUTPUT_FILE} ) From cb1542dd51a34591ca085434f4ed2d6df0d0a85e Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Mon, 27 Nov 2023 16:36:39 +0100 Subject: [PATCH 23/48] lmdk: Fix build of module common functions CMakeLists.txt file of common modules files use isZephyr macro which was undefined on lmdk build scripts. Signed-off-by: Adrian Warecki --- lmdk/cmake/config.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lmdk/cmake/config.cmake b/lmdk/cmake/config.cmake index 6faa6d353215..17e2294613bd 100644 --- a/lmdk/cmake/config.cmake +++ b/lmdk/cmake/config.cmake @@ -35,3 +35,8 @@ function(add_local_sources target) target_sources(${target} PRIVATE ${path}) endforeach() endfunction() + +# Currently loadable modules do not support the Zephyr build system +macro(is_zephyr ret) + set(${ret} FALSE) +endmacro() From 4509d7c0c0d20ad8a2c25d946cf0759116996a2b Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Mon, 27 Nov 2023 16:02:14 +0100 Subject: [PATCH 24/48] lmdk: Update dummy module example Updated dummy module example to use DECLARE_LOADABLE_MODULE_API_VERSION macro. Signed-off-by: Adrian Warecki --- lmdk/modules/dummy/dummy.c | 39 ++++++-------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/lmdk/modules/dummy/dummy.c b/lmdk/modules/dummy/dummy.c index 3d8b3e787f07..7c9f49289542 100644 --- a/lmdk/modules/dummy/dummy.c +++ b/lmdk/modules/dummy/dummy.c @@ -1,41 +1,14 @@ // SPDX-License-Identifier: BSD-3-Clause -// -// Copyright 2023 Intel Corporation. All rights reserved. +/* + * Copyright 2023 Intel Corporation. All rights reserved. + */ #include +#include -/* rimage fails if no .bss section found */ -int bss_workaround; +DECLARE_LOADABLE_MODULE_API_VERSION(dummy); -#define ADSP_BUILD_INFO_FORMAT 0 - -/* these supposed to be defined in some API header file which is not yet available */ -union adsp_api_version { - uint32_t full; - struct { - uint32_t minor : 10; - uint32_t middle : 10; - uint32_t major : 10; - uint32_t reserved : 2; - } fields; -}; - -struct adsp_build_info { - uint32_t format; - union adsp_api_version api_version_number; -}; - -struct adsp_build_info dummy_build_info __attribute__((section(".buildinfo"))) = { - ADSP_BUILD_INFO_FORMAT, - { - ((0x3FF & MAJOR_IADSP_API_VERSION) << 20) | - ((0x3FF & MIDDLE_IADSP_API_VERSION) << 10) | - ((0x3FF & MINOR_IADSP_API_VERSION) << 0) - } -}; - -__attribute__((section(".cmi.text"))) -void *dummyPackageEntryPoint(int a, int b) +void *dummyPackageEntryPoint(void *mod_cfg, void *parent_ppl, void **mod_ptr) { /* supposed to return here a pointer to module interface implementation */ return (void *)0x12345678; From d42911d9744faa95ff23e96b479468cf006d8f49 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Mon, 27 Nov 2023 11:02:22 +0200 Subject: [PATCH 25/48] sof: coherent: Don't mark "struct coherent" as packed On 64-bit systems (i.e: i.MX93), marking "struct coherent" as packed leads to compilation warnings such as: "warning: taking address of packed member of 'struct coherent' may result in an unaligned pointer value" This is because the "list" attribute is found at offset 36, which is not 8B-aligned. In contrast, 32-bit systems don't have this problem as the "list" attribute is found at offset 24 which is 4B-aligned. Since marking "struct coherent" as packed doesn't seem to be necessary, remove this to fix the compilation warnings. On 32-bit systems, 'pahole' shows no difference between the 'packed' and the non-'packed' cases as the fields are already naturally aligned at the moment. A more detailed discussion regarding this issue can be found here: https://github.com/thesofproject/sof/pull/8521. Signed-off-by: Laurentiu Mihalcea --- src/include/sof/coherent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/sof/coherent.h b/src/include/sof/coherent.h index 8e06fb466a66..6c11b6723e98 100644 --- a/src/include/sof/coherent.h +++ b/src/include/sof/coherent.h @@ -17,7 +17,7 @@ #include #include -#define __coherent __attribute__((packed, aligned(DCACHE_LINE_SIZE))) +#define __coherent __aligned(DCACHE_LINE_SIZE) /* * The coherent API allows optimized access to memory by multiple cores, using From 2b23146df6b70d2372d1979dd376af37907f4cc4 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Tue, 14 Nov 2023 12:54:42 +0100 Subject: [PATCH 26/48] rimage: elf_file: Fix elf_free behavior on unopened elf file If more modules are provided in a command line than defined in a toml file, the program outputs an error message. It frees the module structures even though they have not been opened before. This resulted in an error when trying to close a file that was not previously open. Added a check to ensure that a file has been opened before trying to close it. Error handling in the elf_open function has been simplified. Signed-off-by: Adrian Warecki --- tools/rimage/src/elf_file.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/tools/rimage/src/elf_file.c b/tools/rimage/src/elf_file.c index efb9cc912b4e..1891555287e1 100644 --- a/tools/rimage/src/elf_file.c +++ b/tools/rimage/src/elf_file.c @@ -411,18 +411,7 @@ int elf_open(struct elf_file *elf, const char *filename) return 0; err: - free(elf->filename); - free(elf->programs); - - if (elf->file) - fclose(elf->file); - - if (elf->sections) { - for (int i = 0; i < elf->sections_count; i++) - elf_section_header_free(&elf->sections[i]); - - free(elf->sections); - } + elf_free(elf); return ret; } @@ -436,13 +425,17 @@ void elf_free(struct elf_file *elf) int i; free(elf->filename); - fclose(elf->file); + free(elf->programs); - for (i = 0; i < elf->sections_count; i++) - elf_section_header_free(&elf->sections[i]); + if (elf->file) + fclose(elf->file); - free(elf->sections); - free(elf->programs); + if (elf->sections) { + for (i = 0; i < elf->sections_count; i++) + elf_section_header_free(&elf->sections[i]); + + free(elf->sections); + } } int elf_section_read_content(const struct elf_file *elf, const struct elf_section_header *header, From 2b4e484427ec04446e7bc3a03d4089ff323c0c2f Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Tue, 14 Nov 2023 15:04:44 +0100 Subject: [PATCH 27/48] rimage: module: Use file name in error message in module_write_whole_elf By oversight, the error message did not use the file name passed as a parameter to the module_write_whole_elf function. Signed-off-by: Adrian Warecki --- tools/rimage/src/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rimage/src/module.c b/tools/rimage/src/module.c index b150e246ca8c..ffbd4333ed3b 100644 --- a/tools/rimage/src/module.c +++ b/tools/rimage/src/module.c @@ -98,7 +98,7 @@ int module_write_whole_elf(const struct module *module, FILE *out_file, const ch /* write out section data */ count = fwrite(buffer, module->elf.file_size, 1, out_file); if (count != 1) { - ret = file_error("can't write data", "");// TODO: image->out_file); + ret = file_error("can't write data", filename); goto out; } From a4a3b3aed9c9a78087a0c796827ec608d0cd621c Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 28 Nov 2023 20:55:34 +0200 Subject: [PATCH 28/48] include: sof: common.h Fix compilation error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 16d126a36fd821 ("audio: Header files cleanup") removed rtos/panic.h include but this is still needed. Otherwise, we get the following compilation error: /work/repos/sof/src/lib/lib.c: In function ‘memset’: /work/repos/sof/src/lib/lib.c:31: warning: implicit declaration of function ‘sof_panic’ Fixes: 16d126a36fd821 ("audio: Header files cleanup") Signed-off-by: Daniel Baluta --- src/include/sof/common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/sof/common.h b/src/include/sof/common.h index 5c10ba049716..6a875f5a90f7 100644 --- a/src/include/sof/common.h +++ b/src/include/sof/common.h @@ -27,6 +27,7 @@ #if !defined(__ASSEMBLER__) && defined(__XTENSA__) #include +#include #define VERIFY_ALIGN #endif From 0c3ae5ae3c4551e213b8c380b733360db67d496d Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 28 Nov 2023 21:46:13 +0200 Subject: [PATCH 29/48] audio: drc_hifi4: Fix compilation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes following compilation warnings: repos/sof/src/audio/drc/drc_hifi4.c: In function ‘drc_delay_input_sample_s16’: repos/sof/src/audio/drc/drc_hifi4.c:580: warning: assignment from incompatible pointer type repos/sof/src/audio/drc/drc_hifi4.c:581: warning: assignment from incompatible pointer type repos/sof/src/audio/drc/drc_hifi4.c: In function ‘drc_delay_input_sample_s32’: repos/sof/src/audio/drc/drc_hifi4.c:718: warning: assignment from incompatible pointer type repos/sof/src/audio/drc/drc_hifi4.c:719: warning: assignment from incompatible pointer type Signed-off-by: Daniel Baluta --- src/audio/drc/drc_hifi4.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/audio/drc/drc_hifi4.c b/src/audio/drc/drc_hifi4.c index e06966030f6d..93447ecabd90 100644 --- a/src/audio/drc/drc_hifi4.c +++ b/src/audio/drc/drc_hifi4.c @@ -577,8 +577,8 @@ static void drc_delay_input_sample_s16(struct drc_state *state, drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); } - *x = x0; - *y = y0; + *x = (int16_t *)x0; + *y = (int16_t *)y0; } static void drc_s16_default(struct processing_module *mod, @@ -715,8 +715,8 @@ static void drc_delay_input_sample_s32(struct drc_state *state, drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); } - *x = x0; - *y = y0; + *x = (int32_t *)x0; + *y = (int32_t *)y0; } #endif From 5d8e03db6b53e381213f341f51423e2cefef5045 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Mon, 27 Nov 2023 12:21:09 -0600 Subject: [PATCH 30/48] audio: google_rtc_audio_processing: fixup removed struct member This is fixup for a62b7cf1c3f73e3209222d5362a66389e7ae68bf error: 'struct comp_buffer' has no member named 'id' Signed-off-by: Yong Zhi --- src/audio/google/google_rtc_audio_processing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/google/google_rtc_audio_processing.c b/src/audio/google/google_rtc_audio_processing.c index fcf403a1f8bc..3834278ba42e 100644 --- a/src/audio/google/google_rtc_audio_processing.c +++ b/src/audio/google/google_rtc_audio_processing.c @@ -97,7 +97,7 @@ static void google_rtc_audio_processing_params(struct processing_module *mod) list_for_item(source_list, &dev->bsource_list) { sourceb = container_of(source_list, struct comp_buffer, sink_list); - if (IPC4_SINK_QUEUE_ID(sourceb->id) == SOF_AEC_FEEDBACK_QUEUE_ID) + if (IPC4_SINK_QUEUE_ID(buf_get_id(sourceb)) == SOF_AEC_FEEDBACK_QUEUE_ID) ipc4_update_buffer_format(sourceb, &cd->config.reference_fmt); else ipc4_update_buffer_format(sourceb, &mod->priv.cfg.base_cfg.audio_fmt); From 98d5efc3a7b2a51a63248d67dbef0557c9e0b7fa Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Fri, 17 Nov 2023 19:13:22 +0000 Subject: [PATCH 31/48] zephyr/cmake: remove now unused SOF_IPC_PATH variable Fixes commit 1bd9e0d2c7a8 ("cmake/zephyr: decentralize src/ipc/") Signed-off-by: Marc Herbert --- zephyr/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index f9e1f3c40e00..8ea073b878a5 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -48,16 +48,17 @@ zephyr_interface_library_named(SOF) # SOF source paths. cmake_path(SET sof_top_dir NORMALIZE "${CMAKE_CURRENT_SOURCE_DIR}/..") set(SOF_SRC_PATH "${sof_top_dir}/src") + set(SOF_PLATFORM_PATH "${SOF_SRC_PATH}/platform") set(SOF_AUDIO_PATH "${SOF_SRC_PATH}/audio") set(SOF_AUDIO_MODULES_PATH "${SOF_SRC_PATH}/audio/module_adapter/module") set(SOF_SAMPLES_PATH "${SOF_SRC_PATH}/samples") set(SOF_LIB_PATH "${SOF_SRC_PATH}/lib") set(SOF_DRIVERS_PATH "${SOF_SRC_PATH}/drivers") -set(SOF_IPC_PATH "${SOF_SRC_PATH}/ipc") set(SOF_DEBUG_PATH "${SOF_SRC_PATH}/debug") set(SOF_MATH_PATH "${SOF_SRC_PATH}/math") set(SOF_TRACE_PATH "${SOF_SRC_PATH}/trace") + set(RIMAGE_TOP ${sof_top_dir}/tools/rimage) # Save path to rimage configuration files in cmake cache for later use by From 330d73eec17e147449b3187a19d3fc3a5bb364c4 Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Fri, 17 Nov 2023 20:50:23 +0000 Subject: [PATCH 32/48] cmake: a few new add_local_sources[_ifdef]() compatibility macros For reducing CMake duplication and centralization, see #8260 Not used yet. Signed-off-by: Marc Herbert --- scripts/cmake/misc.cmake | 9 +++++++++ zephyr/CMakeLists.txt | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/scripts/cmake/misc.cmake b/scripts/cmake/misc.cmake index ee794780cd09..77ae05ee2754 100644 --- a/scripts/cmake/misc.cmake +++ b/scripts/cmake/misc.cmake @@ -49,6 +49,15 @@ macro(is_zephyr ret) endif() endmacro() +# This macro +# - saves a LOT of repetition, and +# - mimics Zephyr, which helps with compatibility. +macro(add_local_sources_ifdef condition target) + if(${condition}) + add_local_sources(${target} ${ARGN}) + endif() +endmacro() + # Adds sources to target like target_sources, but assumes that # paths are relative to subdirectory. # Works like: diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 8ea073b878a5..a859282102c6 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -128,6 +128,22 @@ macro(is_zephyr ret) endif() endmacro() +# Wrappers for compatibility and re-use of existing, XTOS CMake files. +# Do NOT use these macros in this file or in any other Zephyr-specific +# CMake code. +macro(add_local_sources target) + if (NOT "${target}" STREQUAL "sof") + message(FATAL_ERROR "add_local_sources() target is not 'sof'") + endif() + zephyr_library_sources(${ARGN}) +endmacro() +macro(add_local_sources_ifdef condition target) + if (NOT "${target}" STREQUAL "sof") + message(FATAL_ERROR "add_local_sources_ifdef() target is not 'sof'") + endif() + zephyr_library_sources_ifdef(${condition} ${ARGN}) +endmacro() + add_subdirectory(../src/init/ init_unused_install/) add_subdirectory(../src/ipc/ ipc_unused_install/) From b53f2b08d8a13ba8c624a9dec7ff5113fe611cc4 Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Tue, 28 Nov 2023 00:47:49 +0000 Subject: [PATCH 33/48] module/cmake: simplify thanks to the new add_local_sources() macro Leverage the previous commit. Signed-off-by: Marc Herbert --- src/module/audio/CMakeLists.txt | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/module/audio/CMakeLists.txt b/src/module/audio/CMakeLists.txt index 2d805aa68929..06407bab7520 100644 --- a/src/module/audio/CMakeLists.txt +++ b/src/module/audio/CMakeLists.txt @@ -1,14 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause -is_zephyr(it_is) -if(it_is) ### Zephyr ### - zephyr_library_sources( - source_api.c - sink_api.c - ) -else() ### Not Zephyr ### - add_local_sources(sof - source_api.c - sink_api.c - ) -endif() # Zephyr +add_local_sources(sof + source_api.c + sink_api.c +) From 2ce1f9ea342871034842c562ede6fbfb66764024 Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Fri, 17 Nov 2023 22:23:59 +0000 Subject: [PATCH 34/48] math/cmake: use new macro add_local_sources_ifdef() This makes the code shorter and will help with #8260 Zero functional change. Do not use it when Zephyr use is not conditional. Signed-off-by: Marc Herbert --- src/math/CMakeLists.txt | 38 +++++++++----------------------- src/math/auditory/CMakeLists.txt | 8 ++----- src/math/fft/CMakeLists.txt | 8 ++----- 3 files changed, 15 insertions(+), 39 deletions(-) diff --git a/src/math/CMakeLists.txt b/src/math/CMakeLists.txt index 899810544864..afbc4718fa59 100644 --- a/src/math/CMakeLists.txt +++ b/src/math/CMakeLists.txt @@ -11,49 +11,33 @@ if(CONFIG_CORDIC_FIXED) add_local_sources(sof trig.c) endif() -if(CONFIG_SQRT_FIXED) - add_local_sources(sof sqrt_int16.c) -endif() +add_local_sources_ifdef(CONFIG_SQRT_FIXED sof sqrt_int16.c) -if(CONFIG_MATH_EXP) - add_local_sources(sof exp_fcn.c exp_fcn_hifi.c) -endif() +add_local_sources_ifdef(CONFIG_MATH_EXP sof exp_fcn.c exp_fcn_hifi.c) if(CONFIG_MATH_DECIBELS) add_local_sources(sof decibels.c) endif() -if(CONFIG_NATURAL_LOGARITHM_FIXED) - add_local_sources(sof log_e.c) -endif() +add_local_sources_ifdef(CONFIG_NATURAL_LOGARITHM_FIXED sof log_e.c) -if(CONFIG_COMMON_LOGARITHM_FIXED) - add_local_sources(sof log_10.c) -endif() +add_local_sources_ifdef(CONFIG_COMMON_LOGARITHM_FIXED sof log_10.c) -if(CONFIG_POWER_FIXED) - add_local_sources(sof power.c) -endif() +add_local_sources_ifdef(CONFIG_POWER_FIXED sof power.c) -if(CONFIG_BINARY_LOGARITHM_FIXED) - add_local_sources(sof base2log.c) -endif() +add_local_sources_ifdef(CONFIG_BINARY_LOGARITHM_FIXED sof base2log.c) -if(CONFIG_MATH_FIR) - add_local_sources(sof fir_generic.c fir_hifi2ep.c fir_hifi3.c) -endif() +add_local_sources_ifdef(CONFIG_MATH_FIR sof fir_generic.c fir_hifi2ep.c fir_hifi3.c) if(CONFIG_MATH_FFT) add_subdirectory(fft) endif() -if(CONFIG_MATH_IIR_DF2T) - add_local_sources(sof iir_df2t_generic.c iir_df2t_hifi3.c iir_df2t.c) -endif() +add_local_sources_ifdef(CONFIG_MATH_IIR_DF2T sof + iir_df2t_generic.c iir_df2t_hifi3.c iir_df2t.c) -if(CONFIG_MATH_IIR_DF1) - add_local_sources(sof iir_df1_generic.c iir_df1_hifi3.c iir_df1.c) -endif() +add_local_sources_ifdef(CONFIG_MATH_IIR_DF1 sof + iir_df1_generic.c iir_df1_hifi3.c iir_df1.c) if(CONFIG_MATH_WINDOW) add_local_sources(sof window.c) diff --git a/src/math/auditory/CMakeLists.txt b/src/math/auditory/CMakeLists.txt index c94aed430040..2983e1eb4483 100644 --- a/src/math/auditory/CMakeLists.txt +++ b/src/math/auditory/CMakeLists.txt @@ -2,10 +2,6 @@ add_local_sources(sof auditory.c) -if(CONFIG_MATH_16BIT_MEL_FILTERBANK) - add_local_sources(sof mel_filterbank_16.c) -endif() +add_local_sources_ifdef(CONFIG_MATH_16BIT_MEL_FILTERBANK sof mel_filterbank_16.c) -if(CONFIG_MATH_32BIT_MEL_FILTERBANK) - add_local_sources(sof mel_filterbank_32.c) -endif() +add_local_sources_ifdef(CONFIG_MATH_32BIT_MEL_FILTERBANK sof mel_filterbank_32.c) diff --git a/src/math/fft/CMakeLists.txt b/src/math/fft/CMakeLists.txt index e196f54fa0e9..8d422b93c5b1 100644 --- a/src/math/fft/CMakeLists.txt +++ b/src/math/fft/CMakeLists.txt @@ -2,10 +2,6 @@ add_local_sources(sof fft_common.c) -if(CONFIG_MATH_16BIT_FFT) - add_local_sources(sof fft_16.c fft_16_hifi3.c) -endif() +add_local_sources_ifdef(CONFIG_MATH_16BIT_FFT sof fft_16.c fft_16_hifi3.c) -if(CONFIG_MATH_32BIT_FFT) - add_local_sources(sof fft_32.c fft_32_hifi3.c) -endif() +add_local_sources_ifdef(CONFIG_MATH_32BIT_FFT sof fft_32.c fft_32_hifi3.c) From 5cf1c9c0d67c09437bff0db6e3bda4c7a1b0fbb5 Mon Sep 17 00:00:00 2001 From: "barry.jan" Date: Fri, 10 Nov 2023 15:59:55 +0800 Subject: [PATCH 35/48] topology: Add Waves codec to MT8188 topology Modify sof-mt8188-mt6359 topology so Waves codec can be added to playback in case 'WAVES' is defined. Signed-off-by: barry.jan --- .../xtensa/configs/override/mt8188_chrome_waves.config | 2 ++ tools/topology/topology1/CMakeLists.txt | 1 + tools/topology/topology1/sof-mt8188-mt6359.m4 | 8 ++++++-- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 src/arch/xtensa/configs/override/mt8188_chrome_waves.config diff --git a/src/arch/xtensa/configs/override/mt8188_chrome_waves.config b/src/arch/xtensa/configs/override/mt8188_chrome_waves.config new file mode 100644 index 000000000000..6e0143275ba6 --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8188_chrome_waves.config @@ -0,0 +1,2 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_WAVES_CODEC=y diff --git a/tools/topology/topology1/CMakeLists.txt b/tools/topology/topology1/CMakeLists.txt index 03e2fd4fed3a..8869a8bd7d1b 100644 --- a/tools/topology/topology1/CMakeLists.txt +++ b/tools/topology/topology1/CMakeLists.txt @@ -78,6 +78,7 @@ set(TPLGS "sof-mt8186-mt6366\;sof-mt8186-dts\;-DDTS=`DTS'" "sof-mt8186-mt6366\;sof-mt8186-mt6366-rt1019-rt5682s-waves\;-DWAVES=1" "sof-mt8188-mt6359\;sof-mt8188" + "sof-mt8188-mt6359\;sof-mt8188-waves\;-DWAVES=1" "sof-acp-renoir\;sof-acp" "sof-rn-rt5682-rt1019\;sof-rn-rt5682-rt1019" diff --git a/tools/topology/topology1/sof-mt8188-mt6359.m4 b/tools/topology/topology1/sof-mt8188-mt6359.m4 index f649f366c96d..4244964561db 100644 --- a/tools/topology/topology1/sof-mt8188-mt6359.m4 +++ b/tools/topology/topology1/sof-mt8188-mt6359.m4 @@ -34,19 +34,23 @@ dnl period, priority, core, dnl pcm_min_rate, pcm_max_rate, pipeline_rate, dnl time_domain, sched_comp) +define(`ENDPOINT_NAME', `Speakers') # Low Latency playback pipeline 1 on PCM 16 using max 2 channels of s16le # Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, +PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4), 1, 16, 2, s16le, 1000, 0, 0, 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') +define(`ENDPOINT_NAME', `Headphones') # Low Latency playback pipeline 2 on PCM 17 using max 2 channels of s16le # Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, +PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4), 2, 17, 2, s16le, 1000, 0, 0, 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') # Low Latency capture pipeline 3 on PCM 18 using max 2 channels of s16le # Set 2000us deadline with priority 0 on core 0 From 285c090a10497131cf755dc65c04bddd6a2ece3b Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 22 Nov 2023 14:27:45 -0800 Subject: [PATCH 36/48] topology: Add support for buffer flags Flags have been a part of IPC3 for ages, add support for them in the topology. Signed-off-by: Curtis Malainey --- src/include/kernel/tokens.h | 1 + tools/topology/topology1/m4/buffer.m4 | 5 ++++- tools/tplg_parser/buffer.c | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/include/kernel/tokens.h b/src/include/kernel/tokens.h index 09f82a3063c5..93c4754f831c 100644 --- a/src/include/kernel/tokens.h +++ b/src/include/kernel/tokens.h @@ -33,6 +33,7 @@ /* buffers */ #define SOF_TKN_BUF_SIZE 100 #define SOF_TKN_BUF_CAPS 101 +#define SOF_TKN_BUF_FLAGS 102 /* DAI */ /* Token retired with ABI 3.2, do not use for new capabilities diff --git a/tools/topology/topology1/m4/buffer.m4 b/tools/topology/topology1/m4/buffer.m4 index 376e206c6c09..29a6b5f084a5 100644 --- a/tools/topology/topology1/m4/buffer.m4 +++ b/tools/topology/topology1/m4/buffer.m4 @@ -5,13 +5,16 @@ dnl Define the macro for buffer widget dnl N_BUFFER(name) define(`N_BUFFER', `BUF'PIPELINE_ID`.'$1) -dnl W_BUFFER(name, size, capabilities) +dnl W_BUFFER(name, size, capabilities, [core], [flags]) define(`W_BUFFER', `SectionVendorTuples."'N_BUFFER($1)`_tuples" {' ` tokens "sof_buffer_tokens"' ` tuples."word" {' ` SOF_TKN_BUF_SIZE' STR($2) ` SOF_TKN_BUF_CAPS' STR($3) +`ifelse(`$#', `5', +` SOF_TKN_BUF_FLAGS' STR($5) +,` ')' ` }' `}' `SectionData."'N_BUFFER($1)`_data" {' diff --git a/tools/tplg_parser/buffer.c b/tools/tplg_parser/buffer.c index 7440c3f6cd22..1690693d8a03 100644 --- a/tools/tplg_parser/buffer.c +++ b/tools/tplg_parser/buffer.c @@ -30,6 +30,8 @@ static const struct sof_topology_token buffer_tokens[] = { offsetof(struct sof_ipc_buffer, size), 0}, {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, offsetof(struct sof_ipc_buffer, caps), 0}, + {SOF_TKN_BUF_FLAGS, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_buffer, flags), 0}, }; static const struct sof_topology_token buffer_comp_tokens[] = { From ae21a31d5bb42755445119e83892430db04802d3 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Wed, 8 Nov 2023 13:11:27 +0100 Subject: [PATCH 37/48] module_adapter: Make free, reset and prepare methods optional Simple modules may not need to provide free, reset and prepare functions. To avoid having to provide dummy methods, added an if to check if a module implemented these methods. Signed-off-by: Adrian Warecki --- src/audio/module_adapter/module/generic.c | 46 ++++++++++++----------- src/include/module/module/interface.h | 6 +-- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index ed19c62d69c4..434fd918e778 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -95,9 +95,8 @@ int module_init(struct processing_module *mod, const struct module_interface *in return -EIO; } - /*check interface, there must be one and only one of processing procedure */ - if (!interface->init || !interface->prepare || - !interface->reset || !interface->free || + /* check interface, there must be one and only one of processing procedure */ + if (!interface->init || (!!interface->process + !!interface->process_audio_stream + !!interface->process_raw_data != 1)) { comp_err(dev, "module_init(): comp %d is missing mandatory interfaces", @@ -211,11 +210,13 @@ int module_prepare(struct processing_module *mod, if (mod->priv.state < MODULE_INITIALIZED) return -EPERM; #endif - ret = md->ops->prepare(mod, sources, num_of_sources, sinks, num_of_sinks); - if (ret) { - comp_err(dev, "module_prepare() error %d: module specific prepare failed, comp_id %d", - ret, dev_comp_id(dev)); - return ret; + if (md->ops->prepare) { + ret = md->ops->prepare(mod, sources, num_of_sources, sinks, num_of_sinks); + if (ret) { + comp_err(dev, "module_prepare() error %d: module specific prepare failed, comp_id %d", + ret, dev_comp_id(dev)); + return ret; + } } /* After prepare is done we no longer need runtime configuration @@ -331,14 +332,15 @@ int module_reset(struct processing_module *mod) if (md->state < MODULE_IDLE) return 0; #endif - - ret = md->ops->reset(mod); - if (ret) { - if (ret != PPL_STATUS_PATH_STOP) - comp_err(mod->dev, - "module_reset() error %d: module specific reset() failed for comp %d", - ret, dev_comp_id(mod->dev)); - return ret; + if (md->ops->reset) { + ret = md->ops->reset(mod); + if (ret) { + if (ret != PPL_STATUS_PATH_STOP) + comp_err(mod->dev, + "module_reset() error %d: module specific reset() failed for comp %d", + ret, dev_comp_id(mod->dev)); + return ret; + } } md->cfg.avail = false; @@ -373,13 +375,15 @@ void module_free_all_memory(struct processing_module *mod) int module_free(struct processing_module *mod) { - int ret; + int ret = 0; struct module_data *md = &mod->priv; - ret = md->ops->free(mod); - if (ret) - comp_warn(mod->dev, "module_free(): error: %d for %d", - ret, dev_comp_id(mod->dev)); + if (md->ops->free) { + ret = md->ops->free(mod); + if (ret) + comp_warn(mod->dev, "module_free(): error: %d for %d", + ret, dev_comp_id(mod->dev)); + } /* Free all memory shared by module_adapter & module */ md->cfg.avail = false; diff --git a/src/include/module/module/interface.h b/src/include/module/module/interface.h index c868f227db27..638334982324 100644 --- a/src/include/module/module/interface.h +++ b/src/include/module/module/interface.h @@ -77,7 +77,7 @@ struct module_interface { */ int (*init)(struct processing_module *mod); /** - * Module specific prepare procedure, called as part of module_adapter + * (optional) Module specific prepare procedure, called as part of module_adapter * component preparation in .prepare() */ int (*prepare)(struct processing_module *mod, @@ -196,13 +196,13 @@ struct module_interface { enum module_processing_mode (*get_processing_mode)(struct processing_module *mod); /** - * Module specific reset procedure, called as part of module_adapter component + * (optional) Module specific reset procedure, called as part of module_adapter component * reset in .reset(). This should reset all parameters to their initial stage * and free all memory allocated during prepare(). */ int (*reset)(struct processing_module *mod); /** - * Module specific free procedure, called as part of module_adapter component + * (optional) Module specific free procedure, called as part of module_adapter component * free in .free(). This should free all memory allocated during module initialization. */ int (*free)(struct processing_module *mod); From 347e8353a4ef75a82dfb903ec7f034660afae95f Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Wed, 29 Nov 2023 16:49:55 +0100 Subject: [PATCH 38/48] up_down_mixer: Remove dummy prepare and reset methods The prepare, reset and free methods are now optional in module adapter. Removed unnecessary prepare and reset methods. Signed-off-by: Adrian Warecki --- src/audio/up_down_mixer/up_down_mixer.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/audio/up_down_mixer/up_down_mixer.c b/src/audio/up_down_mixer/up_down_mixer.c index c6e6c6b5bd58..c027c899f31c 100644 --- a/src/audio/up_down_mixer/up_down_mixer.c +++ b/src/audio/up_down_mixer/up_down_mixer.c @@ -398,27 +398,6 @@ static int up_down_mixer_init(struct processing_module *mod) return ret; } -/* just stubs for now. Remove these after making these ops optional in the module adapter */ -static int up_down_mixer_prepare(struct processing_module *mod, - struct sof_source **sources, int num_of_sources, - struct sof_sink **sinks, int num_of_sinks) -{ - struct up_down_mixer_data *cd = module_get_private_data(mod); - struct comp_dev *dev = mod->dev; - - if (!cd->mix_routine) { - comp_err(dev, "up_down_mixer_prepare(): mix routine not initialized"); - return -EINVAL; - } - - return 0; -} - -static int up_down_mixer_reset(struct processing_module *mod) -{ - return 0; -} - static int up_down_mixer_process(struct processing_module *mod, struct input_stream_buffer *input_buffers, int num_input_buffers, @@ -458,9 +437,7 @@ up_down_mixer_process(struct processing_module *mod, static const struct module_interface up_down_mixer_interface = { .init = up_down_mixer_init, - .prepare = up_down_mixer_prepare, .process_audio_stream = up_down_mixer_process, - .reset = up_down_mixer_reset, .free = up_down_mixer_free }; From faf725aba072db80a51c279fad9c247599c20309 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Tue, 28 Nov 2023 15:11:16 +0200 Subject: [PATCH 39/48] Use %zu format for printing size_t variables Currently, building SOF on a 64-bit platform (i.e: i.MX93) leads to compilation warnings such as: "format '%d' expects argument of type 'int', but argument 5 has type 'long unsigned int'" This is because size_t is 64-bit on 64-bit platforms. As such, to get rid of these compilation warnings, use the %zu specifier when printing a size_t variable. Signed-off-by: Laurentiu Mihalcea --- src/audio/data_blob.c | 2 +- src/audio/eq_fir/eq_fir.c | 2 +- src/audio/eq_iir/eq_iir.c | 2 +- src/audio/kpb.c | 18 +++++++++--------- src/audio/module_adapter/module/generic.c | 4 ++-- src/audio/mux/mux.c | 5 +++-- src/audio/selector/selector.c | 2 +- src/audio/src/src.c | 2 +- src/audio/src/src_ipc3.c | 2 +- src/audio/tdfb/tdfb.c | 4 ++-- src/audio/volume/volume_ipc3.c | 4 ++-- src/include/sof/ipc/common.h | 2 +- src/ipc/ipc3/handler.c | 6 +++--- src/ipc/ipc3/host-page-table.c | 2 +- src/samples/audio/smart_amp_test_ipc3.c | 6 +++--- 15 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/audio/data_blob.c b/src/audio/data_blob.c index cbe86cd2c395..b82029bf86a1 100644 --- a/src/audio/data_blob.c +++ b/src/audio/data_blob.c @@ -184,7 +184,7 @@ int comp_data_blob_set(struct comp_data_blob_handler *blob_handler, } #endif - comp_dbg(blob_handler->dev, "comp_data_blob_set_cmd() pos = %d, fragment size = %d", + comp_dbg(blob_handler->dev, "comp_data_blob_set_cmd() pos = %d, fragment size = %zu", pos, fragment_size); /* Check that there is no work-in-progress previous request */ diff --git a/src/audio/eq_fir/eq_fir.c b/src/audio/eq_fir/eq_fir.c index ae684f851406..3068cd0971c2 100644 --- a/src/audio/eq_fir/eq_fir.c +++ b/src/audio/eq_fir/eq_fir.c @@ -262,7 +262,7 @@ static int eq_fir_init(struct processing_module *mod) * blob size is sane. */ if (bs > SOF_EQ_FIR_MAX_SIZE) { - comp_err(dev, "eq_fir_init(): coefficients blob size = %u > SOF_EQ_FIR_MAX_SIZE", + comp_err(dev, "eq_fir_init(): coefficients blob size = %zu > SOF_EQ_FIR_MAX_SIZE", bs); return -EINVAL; } diff --git a/src/audio/eq_iir/eq_iir.c b/src/audio/eq_iir/eq_iir.c index 2a91a08165a2..b5d539759091 100644 --- a/src/audio/eq_iir/eq_iir.c +++ b/src/audio/eq_iir/eq_iir.c @@ -59,7 +59,7 @@ static int eq_iir_init(struct processing_module *mod) /* Check first before proceeding with dev and cd that coefficients blob size is sane */ if (bs > SOF_EQ_IIR_MAX_SIZE) { - comp_err(dev, "eq_iir_init(), coefficients blob size %u exceeds maximum", bs); + comp_err(dev, "eq_iir_init(), coefficients blob size %zu exceeds maximum", bs); return -EINVAL; } diff --git a/src/audio/kpb.c b/src/audio/kpb.c index a7ef3c1e2a45..c6930017d8ef 100644 --- a/src/audio/kpb.c +++ b/src/audio/kpb.c @@ -414,7 +414,7 @@ static int kpb_set_verify_ipc_params(struct comp_dev *dev, ipc_config->size); if (ret) { - comp_err(dev, "kpb_new(): cannot memcpy_s %d bytes into sof_kpb_config (%d)\n", + comp_err(dev, "kpb_new(): cannot memcpy_s %d bytes into sof_kpb_config (%zu)\n", ipc_config->size, sizeof(kpb->config)); return -EINVAL; } @@ -478,7 +478,7 @@ static struct comp_dev *kpb_new(const struct comp_driver *drv, /* make sure data size is not bigger than config space */ if (ipc_config_size > kpb_config_size) { - comp_cl_err(&comp_kpb, "kpb_new(): ipc config size %u too big", + comp_cl_err(&comp_kpb, "kpb_new(): ipc config size %zu too big", ipc_config_size); return NULL; } @@ -579,7 +579,7 @@ static size_t kpb_allocate_history_buffer(struct comp_data *kpb, /* We managed to allocate a block of ca_size. * Now we initialize it. */ - comp_cl_info(&comp_kpb, "kpb new memory block: %d", + comp_cl_info(&comp_kpb, "kpb new memory block: %zu", ca_size); allocated_size += ca_size; hb->start_addr = new_mem_block; @@ -628,7 +628,7 @@ static size_t kpb_allocate_history_buffer(struct comp_data *kpb, } } - comp_cl_info(&comp_kpb, "kpb_allocate_history_buffer(): allocated %d bytes", + comp_cl_info(&comp_kpb, "kpb_allocate_history_buffer(): allocated %zu bytes", allocated_size); return allocated_size; @@ -1339,7 +1339,7 @@ static int kpb_copy(struct comp_dev *dev) comp_update_buffer_consume(source, copy_bytes); } else { - comp_warn(dev, "kpb_copy(): buffering skipped (no data to copy, avail %d, free %d", + comp_warn(dev, "kpb_copy(): buffering skipped (no data to copy, avail %d, free %zu", audio_stream_get_avail_bytes(&source->stream), kpb->hd.free); } @@ -1837,7 +1837,7 @@ static enum task_state kpb_draining_task(void *arg) * while we were draining real time stream could provided * new data which needs to be copy to host. */ - comp_cl_info(&comp_kpb, "kpb: update drain_req by %d", + comp_cl_info(&comp_kpb, "kpb: update drain_req by %zu", *rt_stream_update); kpb_lock(kpb); drain_req += *rt_stream_update; @@ -2295,7 +2295,7 @@ static inline bool validate_host_params(struct comp_dev *dev, if (!host_period_size || !host_buffer_size) { /* Wrong host params */ - comp_err(dev, "kpb: host_period_size (%d) cannot be 0 and host_buffer_size (%d) cannot be 0", + comp_err(dev, "kpb: host_period_size (%zu) cannot be 0 and host_buffer_size (%zu) cannot be 0", host_period_size, host_buffer_size); return false; } else if (HOST_BUFFER_MIN_SIZE(hb_size_req, kpb->config.channels) > @@ -2303,7 +2303,7 @@ static inline bool validate_host_params(struct comp_dev *dev, /* Host buffer size is too small - history data * may get overwritten. */ - comp_warn(dev, "kpb: host_buffer_size (%d) must be at least %d", + comp_warn(dev, "kpb: host_buffer_size (%zu) must be at least %zu", host_buffer_size, HOST_BUFFER_MIN_SIZE(hb_size_req, kpb->config.channels)); } else if (kpb->sync_draining_mode) { @@ -2318,7 +2318,7 @@ static inline bool validate_host_params(struct comp_dev *dev, */ if ((host_period_size / KPB_DRAIN_NUM_OF_PPL_PERIODS_AT_ONCE) < pipeline_period_size) { - comp_err(dev, "kpb: host_period_size (%d) must be at least %d * %d", + comp_err(dev, "kpb: host_period_size (%zu) must be at least %d * %zu", host_period_size, KPB_DRAIN_NUM_OF_PPL_PERIODS_AT_ONCE, pipeline_period_size); diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 434fd918e778..d91a59bbdf31 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -30,7 +30,7 @@ int module_load_config(struct comp_dev *dev, const void *cfg, size_t size) comp_dbg(dev, "module_load_config() start"); if (!cfg || !size) { - comp_err(dev, "module_load_config(): wrong input params! dev %x, cfg %x size %d", + comp_err(dev, "module_load_config(): wrong input params! dev %x, cfg %x size %zu", (uint32_t)dev, (uint32_t)cfg, size); return -EINVAL; } @@ -452,7 +452,7 @@ int module_set_configuration(struct processing_module *mod, return 0; if (md->new_cfg_size > MAX_BLOB_SIZE) { - comp_err(dev, "module_set_configuration(): error: blob size is too big cfg size %d, allowed %d", + comp_err(dev, "module_set_configuration(): error: blob size is too big cfg size %zu, allowed %d", md->new_cfg_size, MAX_BLOB_SIZE); return -EINVAL; } diff --git a/src/audio/mux/mux.c b/src/audio/mux/mux.c index de16ee754c98..bc3836473df4 100644 --- a/src/audio/mux/mux.c +++ b/src/audio/mux/mux.c @@ -215,7 +215,8 @@ static int mux_demux_common_init(struct processing_module *mod) comp_dbg(dev, "mux_init()"); if (cfg->size > MUX_BLOB_MAX_SIZE) { - comp_err(dev, "mux_init(): blob size %d exceeds %d", cfg->size, MUX_BLOB_MAX_SIZE); + comp_err(dev, "mux_init(): blob size %zu exceeds %zu", + cfg->size, MUX_BLOB_MAX_SIZE); return -EINVAL; } @@ -575,7 +576,7 @@ static int mux_prepare(struct processing_module *mod, config = comp_get_data_blob(cd->model_handler, &blob_size, NULL); if (blob_size > MUX_BLOB_MAX_SIZE) { - comp_err(dev, "mux_prepare(): illegal blob size %d", blob_size); + comp_err(dev, "mux_prepare(): illegal blob size %zu", blob_size); return -EINVAL; } diff --git a/src/audio/selector/selector.c b/src/audio/selector/selector.c index 97126168ac77..55bf2af608d4 100644 --- a/src/audio/selector/selector.c +++ b/src/audio/selector/selector.c @@ -458,7 +458,7 @@ static int selector_prepare(struct comp_dev *dev) sink_size = audio_stream_get_size(&sinkb->stream); if (sink_size < cd->sink_period_bytes) { - comp_err(dev, "selector_prepare(): sink buffer size %d is insufficient < %d", + comp_err(dev, "selector_prepare(): sink buffer size %zu is insufficient < %d", sink_size, cd->sink_period_bytes); ret = -ENOMEM; goto err; diff --git a/src/audio/src/src.c b/src/audio/src/src.c index 0be34245189a..731d29680668 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -568,7 +568,7 @@ int src_params_general(struct processing_module *mod, cd->delay_lines = rballoc(0, SOF_MEM_CAPS_RAM, delay_lines_size); if (!cd->delay_lines) { - comp_err(dev, "src_params(): failed to alloc cd->delay_lines, delay_lines_size = %u", + comp_err(dev, "src_params(): failed to alloc cd->delay_lines, delay_lines_size = %zu", delay_lines_size); return -EINVAL; } diff --git a/src/audio/src/src_ipc3.c b/src/audio/src/src_ipc3.c index b2c2fbfd0930..ad1f1ed05a36 100644 --- a/src/audio/src/src_ipc3.c +++ b/src/audio/src/src_ipc3.c @@ -170,7 +170,7 @@ int src_init(struct processing_module *mod) } if (!cfg->init_data || cfg->size != sizeof(cd->ipc_config)) { - comp_err(dev, "src_init(): Missing or bad size (%u) init data", + comp_err(dev, "src_init(): Missing or bad size (%zu) init data", cfg->size); return -EINVAL; } diff --git a/src/audio/tdfb/tdfb.c b/src/audio/tdfb/tdfb.c index 282fc5983e1f..7a7f751b1548 100644 --- a/src/audio/tdfb/tdfb.c +++ b/src/audio/tdfb/tdfb.c @@ -357,7 +357,7 @@ static int tdfb_init(struct processing_module *mod) /* Check first that configuration blob size is sane */ if (bs > SOF_TDFB_MAX_SIZE) { - comp_err(dev, "tdfb_init() error: configuration blob size = %u > %d", + comp_err(dev, "tdfb_init() error: configuration blob size = %zu > %d", bs, SOF_TDFB_MAX_SIZE); return -EINVAL; } @@ -579,7 +579,7 @@ static int tdfb_prepare(struct processing_module *mod, /* Initialize tracking */ ret = tdfb_direction_init(cd, rate, source_channels); if (!ret) { - comp_info(dev, "max_lag = %d, xcorr_size = %d", + comp_info(dev, "max_lag = %d, xcorr_size = %zu", cd->direction.max_lag, cd->direction.d_size); comp_info(dev, "line_array = %d, a_step = %d, a_offs = %d", (int)cd->direction.line_array, cd->config->angle_enum_mult, diff --git a/src/audio/volume/volume_ipc3.c b/src/audio/volume/volume_ipc3.c index 4a68d4a6d2df..2c65f6bba2dc 100644 --- a/src/audio/volume/volume_ipc3.c +++ b/src/audio/volume/volume_ipc3.c @@ -79,7 +79,7 @@ int volume_init(struct processing_module *mod) int i; if (!vol || cfg->size != sizeof(*vol)) { - comp_err(dev, "volume_init(): No configuration data or bad data size %u", + comp_err(dev, "volume_init(): No configuration data or bad data size %zu", cfg->size); return -EINVAL; } @@ -95,7 +95,7 @@ int volume_init(struct processing_module *mod) cd->vol = rmalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, vol_size); if (!cd->vol) { rfree(cd); - comp_err(dev, "volume_init(): Failed to allocate %d", vol_size); + comp_err(dev, "volume_init(): Failed to allocate %zu", vol_size); return -ENOMEM; } diff --git a/src/include/sof/ipc/common.h b/src/include/sof/ipc/common.h index 0c0876bb983e..ef2e8c8d7f3c 100644 --- a/src/include/sof/ipc/common.h +++ b/src/include/sof/ipc/common.h @@ -34,7 +34,7 @@ extern struct tr_ctx ipc_tr; /* convenience error trace for mismatched internal structures */ #define IPC_SIZE_ERROR_TRACE(ctx, object) \ - tr_err(ctx, "ipc: size %d expected %d", \ + tr_err(ctx, "ipc: size %d expected %zu", \ (object).hdr.size, sizeof(object)) /* Returns pipeline source component */ diff --git a/src/ipc/ipc3/handler.c b/src/ipc/ipc3/handler.c index a72a9dc2e1a1..b7884fcda307 100644 --- a/src/ipc/ipc3/handler.c +++ b/src/ipc/ipc3/handler.c @@ -82,12 +82,12 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); ___ret = memcpy_s(rx, rx_size, tx, tx->size); \ assert(!___ret); \ bzero((char *)rx + tx->size, rx_size - tx->size);\ - tr_dbg(&ipc_tr, "ipc: hdr 0x%x rx (%d) > tx (%d)",\ + tr_dbg(&ipc_tr, "ipc: hdr 0x%x rx (%zu) > tx (%d)",\ rx->cmd, rx_size, tx->size); \ } else if (tx->size > rx_size) { \ ___ret = memcpy_s(rx, rx_size, tx, rx_size); \ assert(!___ret); \ - tr_warn(&ipc_tr, "ipc: hdr 0x%x tx (%d) > rx (%d)",\ + tr_warn(&ipc_tr, "ipc: hdr 0x%x tx (%d) > rx (%zu)",\ rx->cmd, tx->size, rx_size); \ } else { \ ___ret = memcpy_s(rx, rx_size, tx, rx_size); \ @@ -252,7 +252,7 @@ static int ipc_stream_pcm_params(uint32_t stream) } if (sizeof(pcm_params) + pcm_params.params.ext_data_length > SOF_IPC_MSG_MAX_SIZE) { - ipc_cmd_err(&ipc_tr, "pcm_params ext_data_length invalid size %d max allowed %d", + ipc_cmd_err(&ipc_tr, "pcm_params ext_data_length invalid size %d max allowed %zu", pcm_params.params.ext_data_length, SOF_IPC_MSG_MAX_SIZE - sizeof(pcm_params)); return -EINVAL; diff --git a/src/ipc/ipc3/host-page-table.c b/src/ipc/ipc3/host-page-table.c index bd6b9b5197b6..3019da987be2 100644 --- a/src/ipc/ipc3/host-page-table.c +++ b/src/ipc/ipc3/host-page-table.c @@ -45,7 +45,7 @@ static int ipc_parse_page_descriptors(uint8_t *page_table, elem_array->elems = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(struct dma_sg_elem) * ring->pages); if (!elem_array->elems) { - tr_err(&ipc_tr, "ipc_parse_page_descriptors(): There is no heap free with this block size: %d", + tr_err(&ipc_tr, "ipc_parse_page_descriptors(): There is no heap free with this block size: %zu", sizeof(struct dma_sg_elem) * ring->pages); return -ENOMEM; } diff --git a/src/samples/audio/smart_amp_test_ipc3.c b/src/samples/audio/smart_amp_test_ipc3.c index 3fced159364f..fcb9da36e66e 100644 --- a/src/samples/audio/smart_amp_test_ipc3.c +++ b/src/samples/audio/smart_amp_test_ipc3.c @@ -112,11 +112,11 @@ static int smart_amp_set_config(struct comp_dev *dev, ASSUME_ALIGNED(&cdata->data->data, sizeof(uint32_t)); bs = cfg->size; - comp_dbg(dev, "smart_amp_set_config(), actual blob size = %u, expected blob size = %u", + comp_dbg(dev, "smart_amp_set_config(), actual blob size = %zu, expected blob size = %zu", bs, sizeof(struct sof_smart_amp_config)); if (bs != sizeof(struct sof_smart_amp_config)) { - comp_err(dev, "smart_amp_set_config(): invalid blob size, actual blob size = %u, expected blob size = %u", + comp_err(dev, "smart_amp_set_config(): invalid blob size, actual blob size = %zu, expected blob size = %zu", bs, sizeof(struct sof_smart_amp_config)); return -EINVAL; } @@ -137,7 +137,7 @@ static int smart_amp_get_config(struct comp_dev *dev, /* Copy back to user space */ bs = sad->config.size; - comp_dbg(dev, "smart_amp_set_config(), actual blob size = %u, expected blob size = %u", + comp_dbg(dev, "smart_amp_set_config(), actual blob size = %zu, expected blob size = %zu", bs, sizeof(struct sof_smart_amp_config)); if (bs == 0 || bs > size) From a945ec45e777b4370970c09a4127fff4d1028171 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Wed, 29 Nov 2023 13:24:02 +0200 Subject: [PATCH 40/48] imx93_a55: memory.h: Add ULL suffix on MU_BASE's definition Currently, the imx_mu_write() and imx_mu_read() functions cast MU_BASE's value to a pointer. On 64-bit platforms such as i.MX93 this leads to compilation warnings because the value of MU_BASE is 32-bit while the pointers are 64-bit. As such, to solve this, add the ULL suffix to the definition of MU_BASE to make it 64-bit. Signed-off-by: Laurentiu Mihalcea --- src/platform/imx93_a55/include/platform/lib/memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/imx93_a55/include/platform/lib/memory.h b/src/platform/imx93_a55/include/platform/lib/memory.h index 579c2b43d502..77ca3ec6103b 100644 --- a/src/platform/imx93_a55/include/platform/lib/memory.h +++ b/src/platform/imx93_a55/include/platform/lib/memory.h @@ -49,7 +49,7 @@ #define HEAPMEM_SIZE 0x00010000 /* SOF uses A side of the WAKEUPMIX MU */ -#define MU_BASE 0x42430000 +#define MU_BASE 0x42430000ULL /* SOF uses EDMA2 (a.k.a EDMA4 in the TRM) */ #define EDMA2_BASE 0x42010000 From a8ad6ebfc852a9248508b1308665f75beaf87b9e Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Wed, 29 Nov 2023 13:44:48 +0200 Subject: [PATCH 41/48] Cast pointers to size_t instead of uint32_t when printing On 64-bit platforms such as i.MX93 the pointers are 64-bit. As such, casting them to uint32_t leads to compilation warnings such as: "cast to pointer from integer of different size" To fix this, cast to size_t which, on 32-bit platforms is 32-bit and 64-bit on 64-bit platforms. Printing will be done via "%zx". Signed-off-by: Laurentiu Mihalcea --- src/audio/module_adapter/module/generic.c | 4 ++-- src/audio/module_adapter/module_adapter.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index d91a59bbdf31..3ab9f991feb9 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -30,8 +30,8 @@ int module_load_config(struct comp_dev *dev, const void *cfg, size_t size) comp_dbg(dev, "module_load_config() start"); if (!cfg || !size) { - comp_err(dev, "module_load_config(): wrong input params! dev %x, cfg %x size %zu", - (uint32_t)dev, (uint32_t)cfg, size); + comp_err(dev, "module_load_config(): wrong input params! dev %zx, cfg %zx size %zu", + (size_t)dev, (size_t)cfg, size); return -EINVAL; } diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 31482e223c23..5bdfb68028dc 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -47,8 +47,8 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv, comp_cl_dbg(drv, "module_adapter_new() start"); if (!config) { - comp_cl_err(drv, "module_adapter_new(), wrong input params! drv = %x config = %x", - (uint32_t)drv, (uint32_t)config); + comp_cl_err(drv, "module_adapter_new(), wrong input params! drv = %zx config = %zx", + (size_t)drv, (size_t)config); return NULL; } From 089435e008d08d4300637dae0804a2f8e793c60f Mon Sep 17 00:00:00 2001 From: Joe Cheng Date: Mon, 20 Nov 2023 16:43:14 +0800 Subject: [PATCH 42/48] module_adapter: dts: import DTS library from third_party Update the path to import DTS library from third_party/lib/ instead of src/audio/module_adapter/lib/release/. This action was requested in PR#8379. Signed-off-by: Joe Cheng --- src/audio/module_adapter/CMakeLists.txt | 3 ++- zephyr/CMakeLists.txt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/audio/module_adapter/CMakeLists.txt b/src/audio/module_adapter/CMakeLists.txt index 72dc1492b3ff..e79ca9acf8a7 100644 --- a/src/audio/module_adapter/CMakeLists.txt +++ b/src/audio/module_adapter/CMakeLists.txt @@ -69,7 +69,8 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) if (CONFIG_DTS_CODEC_STUB) add_local_sources(sof module/dts/dts_stub.c) else() - sof_add_static_library(DtsCodec ${CMAKE_CURRENT_LIST_DIR}/lib/release/libdts-sof-interface-i32.a) + sof_add_static_library(DtsCodec + ${SOF_ROOT_SOURCE_DIRECTORY}/third_party/lib/libdts-sof-interface-i32.a) endif() endif() diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index a859282102c6..f9abbf86e82e 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -794,7 +794,8 @@ if (CONFIG_DTS_CODEC) ${SOF_AUDIO_PATH}/module_adapter/module/dts/dts_stub.c ) else() - zephyr_library_import(DtsCodec ${SOF_AUDIO_PATH}/module_adapter/lib/release/libdts-sof-interface-i32.a) + zephyr_library_import(DtsCodec + ${sof_top_dir}/third_party/lib/libdts-sof-interface-i32.a) endif() endif() From 9dfe9c1ef6a3d79cf42c3ca0161c752949a7ed21 Mon Sep 17 00:00:00 2001 From: Joe Cheng Date: Tue, 21 Nov 2023 10:59:49 +0800 Subject: [PATCH 43/48] module_adapter: dts: update the path to include DTS header files Update the path to include DTS header files from third_party/include/. This action was requested in PR#8379. Signed-off-by: Joe Cheng --- src/audio/module_adapter/module/dts/dts.c | 2 +- src/audio/module_adapter/module/dts/dts_stub.c | 2 +- .../sof/audio/dts => third_party/include}/DtsSofInterface.h | 0 .../audio/dts => third_party/include}/DtsSofInterfaceResult.h | 0 .../audio/dts => third_party/include}/DtsSofInterfaceVersion.h | 0 5 files changed, 2 insertions(+), 2 deletions(-) rename {src/include/sof/audio/dts => third_party/include}/DtsSofInterface.h (100%) rename {src/include/sof/audio/dts => third_party/include}/DtsSofInterfaceResult.h (100%) rename {src/include/sof/audio/dts => third_party/include}/DtsSofInterfaceVersion.h (100%) diff --git a/src/audio/module_adapter/module/dts/dts.c b/src/audio/module_adapter/module/dts/dts.c index 78ca727b0a5c..cd843d8077f9 100644 --- a/src/audio/module_adapter/module/dts/dts.c +++ b/src/audio/module_adapter/module/dts/dts.c @@ -6,7 +6,7 @@ #include #include -#include +#include "DtsSofInterface.h" LOG_MODULE_REGISTER(dts, CONFIG_SOF_LOG_LEVEL); diff --git a/src/audio/module_adapter/module/dts/dts_stub.c b/src/audio/module_adapter/module/dts/dts_stub.c index 140ef2836a3e..dc81f3db251e 100644 --- a/src/audio/module_adapter/module/dts/dts_stub.c +++ b/src/audio/module_adapter/module/dts/dts_stub.c @@ -4,7 +4,7 @@ // // Author: Curtis Malainey -#include +#include "DtsSofInterface.h" DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceInit( DtsSofInterfaceInst **ppInst, diff --git a/src/include/sof/audio/dts/DtsSofInterface.h b/third_party/include/DtsSofInterface.h similarity index 100% rename from src/include/sof/audio/dts/DtsSofInterface.h rename to third_party/include/DtsSofInterface.h diff --git a/src/include/sof/audio/dts/DtsSofInterfaceResult.h b/third_party/include/DtsSofInterfaceResult.h similarity index 100% rename from src/include/sof/audio/dts/DtsSofInterfaceResult.h rename to third_party/include/DtsSofInterfaceResult.h diff --git a/src/include/sof/audio/dts/DtsSofInterfaceVersion.h b/third_party/include/DtsSofInterfaceVersion.h similarity index 100% rename from src/include/sof/audio/dts/DtsSofInterfaceVersion.h rename to third_party/include/DtsSofInterfaceVersion.h From ce4acfd1717e83816c732b6094aeb6c77e169d05 Mon Sep 17 00:00:00 2001 From: Joe Cheng Date: Tue, 21 Nov 2023 16:18:56 +0800 Subject: [PATCH 44/48] audio: dts: move dts code to standalone folder This was suggested in PR#8389. Since the module uses module_interface, it doesn't have to put it under module_adaper/module/. Move dts codes from src/audo/module_adapter/module/ to src/audio/codec. Signed-off-by: Joe Cheng --- src/audio/CMakeLists.txt | 3 +++ src/audio/Kconfig | 2 ++ src/audio/codec/CMakeLists.txt | 12 +++++++++++ src/audio/codec/Kconfig | 20 +++++++++++++++++++ .../module => codec}/dts/dts.c | 0 .../module => codec}/dts/dts_stub.c | 0 src/audio/module_adapter/CMakeLists.txt | 11 ---------- src/audio/module_adapter/Kconfig | 19 ------------------ zephyr/CMakeLists.txt | 4 ++-- 9 files changed, 39 insertions(+), 32 deletions(-) create mode 100644 src/audio/codec/CMakeLists.txt create mode 100644 src/audio/codec/Kconfig rename src/audio/{module_adapter/module => codec}/dts/dts.c (100%) rename src/audio/{module_adapter/module => codec}/dts/dts_stub.c (100%) diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index 101edc2a838e..8c4c6006cade 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -112,6 +112,9 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) if(CONFIG_COMP_CHAIN_DMA) add_local_sources(sof chain_dma.c) endif() + if(CONFIG_DTS_CODEC) + add_subdirectory(codec) + endif() return() endif() diff --git a/src/audio/Kconfig b/src/audio/Kconfig index 0c4944926ac2..07ac76929059 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -151,6 +151,8 @@ rsource "rtnr/Kconfig" rsource "mfcc/Kconfig" +rsource "codec/Kconfig" + endmenu # "Audio components" menu "Data formats" diff --git a/src/audio/codec/CMakeLists.txt b/src/audio/codec/CMakeLists.txt new file mode 100644 index 000000000000..d32c421ad997 --- /dev/null +++ b/src/audio/codec/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_DTS_CODEC) + add_local_sources(sof dts/dts.c) + target_compile_definitions(sof PRIVATE -DDTS_MATH_INT32 -DDTS_XTENSA) + if (CONFIG_DTS_CODEC_STUB) + add_local_sources(sof dts/dts_stub.c) + else() + sof_add_static_library(DtsCodec + ${SOF_ROOT_SOURCE_DIRECTORY}/third_party/lib/libdts-sof-interface-i32.a) + endif() +endif() diff --git a/src/audio/codec/Kconfig b/src/audio/codec/Kconfig new file mode 100644 index 000000000000..4823df512554 --- /dev/null +++ b/src/audio/codec/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config DTS_CODEC + bool "DTS codec" + default n + select DTS_CODEC_STUB if COMP_STUBS + help + Select to include DTS codec. + In order to compile with this option enabled, a pre-compiled static library + must be provided by DTS for your target platform. If this library is not present + then compilation errors will occur. + For more information, please contact sales@xperi.com + +config DTS_CODEC_STUB + bool "DTS codec stub" + depends on DTS_CODEC + default n + help + Select to include DTS codec stub library. This is meant for testing and CI + purposes only. diff --git a/src/audio/module_adapter/module/dts/dts.c b/src/audio/codec/dts/dts.c similarity index 100% rename from src/audio/module_adapter/module/dts/dts.c rename to src/audio/codec/dts/dts.c diff --git a/src/audio/module_adapter/module/dts/dts_stub.c b/src/audio/codec/dts/dts_stub.c similarity index 100% rename from src/audio/module_adapter/module/dts/dts_stub.c rename to src/audio/codec/dts/dts_stub.c diff --git a/src/audio/module_adapter/CMakeLists.txt b/src/audio/module_adapter/CMakeLists.txt index e79ca9acf8a7..ef80b9050b5e 100644 --- a/src/audio/module_adapter/CMakeLists.txt +++ b/src/audio/module_adapter/CMakeLists.txt @@ -63,16 +63,5 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) # folder with Waves API must be among include directories endif() - if(CONFIG_DTS_CODEC) - add_local_sources(sof module/dts/dts.c) - target_compile_definitions(sof PRIVATE -DDTS_MATH_INT32 -DDTS_XTENSA) - if (CONFIG_DTS_CODEC_STUB) - add_local_sources(sof module/dts/dts_stub.c) - else() - sof_add_static_library(DtsCodec - ${SOF_ROOT_SOURCE_DIRECTORY}/third_party/lib/libdts-sof-interface-i32.a) - endif() - endif() - return() endif() diff --git a/src/audio/module_adapter/Kconfig b/src/audio/module_adapter/Kconfig index ba8370bf6f6e..8ebe5ecf06bc 100644 --- a/src/audio/module_adapter/Kconfig +++ b/src/audio/module_adapter/Kconfig @@ -176,25 +176,6 @@ endif # Cadence Select to build the waves codec with a stub file. This should only be used for testing or CI. - config DTS_CODEC - bool "DTS codec" - default n - select DTS_CODEC_STUB if COMP_STUBS - help - Select to include DTS codec. - In order to compile with this option enabled, a pre-compiled static library - must be provided by DTS for your target platform. If this library is not present - then compilation errors will occur. - For more information, please contact sales@xperi.com - - config DTS_CODEC_STUB - bool "DTS codec stub" - depends on DTS_CODEC - default n - help - Select to include DTS codec stub library. This is meant for testing and CI - purposes only. - config INTEL_MODULES bool "Intel modules" default n diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index f9abbf86e82e..c5289abc9af9 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -786,12 +786,12 @@ zephyr_library_sources_ifdef(CONFIG_COMP_GOOGLE_HOTWORD_DETECT ) zephyr_library_sources_ifdef(CONFIG_DTS_CODEC - ${SOF_AUDIO_PATH}/module_adapter/module/dts/dts.c + ${SOF_AUDIO_PATH}/codec/dts/dts.c ) if (CONFIG_DTS_CODEC) if (CONFIG_DTS_CODEC_STUB) zephyr_library_sources( - ${SOF_AUDIO_PATH}/module_adapter/module/dts/dts_stub.c + ${SOF_AUDIO_PATH}/codec/dts/dts_stub.c ) else() zephyr_library_import(DtsCodec From fa03f058586b6b76a5e2aa405b89f3003d2effbb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 27 Nov 2023 14:44:35 +0100 Subject: [PATCH 45/48] module-adapter: remove .cmd() from IPC4 struct comp_ops::cmd() is only used for IPC3, remove it and comp_cmd() from the IPC4 version. Signed-off-by: Guennadi Liakhovetski --- src/audio/google/google_hotword_detect.c | 4 + src/audio/igo_nr/igo_nr.c | 36 ++--- src/audio/kpb.c | 7 +- src/audio/module_adapter/module_adapter.c | 123 ------------------ .../module_adapter/module_adapter_ipc3.c | 122 +++++++++++++++++ src/audio/rtnr/rtnr.c | 4 + src/audio/selector/selector.c | 4 + src/audio/smart_amp/smart_amp.c | 4 + src/audio/tone.c | 4 + src/include/sof/audio/component.h | 2 + src/include/sof/audio/component_ext.h | 2 + .../sof/audio/module_adapter/module/generic.h | 12 +- .../sof/audio/module_adapter/module/modules.h | 40 +++--- src/library_manager/lib_manager.c | 3 +- 14 files changed, 203 insertions(+), 164 deletions(-) diff --git a/src/audio/google/google_hotword_detect.c b/src/audio/google/google_hotword_detect.c index cf2c4ea3f00c..be45cd9d2d08 100644 --- a/src/audio/google/google_hotword_detect.c +++ b/src/audio/google/google_hotword_detect.c @@ -224,6 +224,7 @@ static int ghd_setup_model(struct comp_dev *dev) return 0; } +#if CONFIG_IPC_MAJOR_3 static int ghd_ctrl_set_bin_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) { @@ -309,6 +310,7 @@ static int ghd_cmd(struct comp_dev *dev, int cmd, void *data, return -EINVAL; } } +#endif static int ghd_trigger(struct comp_dev *dev, int cmd) { @@ -459,7 +461,9 @@ static const struct comp_driver ghd_driver = { .create = ghd_create, .free = ghd_free, .params = ghd_params, +#if CONFIG_IPC_MAJOR_3 .cmd = ghd_cmd, +#endif .trigger = ghd_trigger, .copy = ghd_copy, .prepare = ghd_prepare, diff --git a/src/audio/igo_nr/igo_nr.c b/src/audio/igo_nr/igo_nr.c index 19d0cc01db46..47750ba22151 100644 --- a/src/audio/igo_nr/igo_nr.c +++ b/src/audio/igo_nr/igo_nr.c @@ -441,6 +441,23 @@ static int32_t igo_nr_params(struct comp_dev *dev, return cd->invalid_param ? -EINVAL : 0; } +static int32_t igo_nr_check_config_validity(struct comp_dev *dev, + struct comp_data *cd) +{ + struct sof_igo_nr_config *p_config = comp_get_data_blob(cd->model_handler, NULL, NULL); + + if (!p_config) { + comp_err(dev, "igo_nr_check_config_validity() error: invalid cd->model_handler"); + return -EINVAL; + } else if (p_config->active_channel_idx >= SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "igo_nr_check_config_validity() error: invalid active_channel_idxs"); + return -EINVAL; + } else { + return 0; + } +} + +#if CONFIG_IPC_MAJOR_3 static inline void igo_nr_set_chan_process(struct comp_dev *dev, int32_t chan) { struct comp_data *cd = comp_get_drvdata(dev); @@ -503,22 +520,6 @@ static int32_t igo_nr_cmd_get_value(struct comp_dev *dev, struct sof_ipc_ctrl_da return ret; } -static int32_t igo_nr_check_config_validity(struct comp_dev *dev, - struct comp_data *cd) -{ - struct sof_igo_nr_config *p_config = comp_get_data_blob(cd->model_handler, NULL, NULL); - - if (!p_config) { - comp_err(dev, "igo_nr_check_config_validity() error: invalid cd->model_handler"); - return -EINVAL; - } else if (p_config->active_channel_idx >= SOF_IPC_MAX_CHANNELS) { - comp_err(dev, "igo_nr_check_config_validity() error: invalid active_channel_idxs"); - return -EINVAL; - } else { - return 0; - } -} - static int32_t igo_nr_cmd_set_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) { @@ -610,6 +611,7 @@ static int32_t igo_nr_cmd(struct comp_dev *dev, return -EINVAL; } } +#endif static void igo_nr_process(struct comp_dev *dev, struct comp_buffer *source, @@ -822,7 +824,9 @@ static const struct comp_driver comp_igo_nr = { .create = igo_nr_new, .free = igo_nr_free, .params = igo_nr_params, +#if CONFIG_IPC_MAJOR_3 .cmd = igo_nr_cmd, +#endif .copy = igo_nr_copy, .prepare = igo_nr_prepare, .reset = igo_nr_reset, diff --git a/src/audio/kpb.c b/src/audio/kpb.c index c6930017d8ef..43f75519850e 100644 --- a/src/audio/kpb.c +++ b/src/audio/kpb.c @@ -926,6 +926,7 @@ static int kpb_prepare(struct comp_dev *dev) return ret; } +#if CONFIG_IPC_MAJOR_3 /** * \brief Used to pass standard and bespoke commands (with data) to component. * \param[in,out] dev - Volume base component device. @@ -938,6 +939,7 @@ static int kpb_cmd(struct comp_dev *dev, int cmd, void *data, { return 0; } +#endif /** * \brief Resets KPB component. @@ -2577,17 +2579,18 @@ static const struct comp_driver comp_kpb = { .ops = { .create = kpb_new, .free = kpb_free, - .cmd = kpb_cmd, .trigger = kpb_trigger, .copy = kpb_copy, .prepare = kpb_prepare, .reset = kpb_reset, .params = kpb_params, .set_large_config = kpb_set_large_config, -#ifdef CONFIG_IPC_MAJOR_4 +#if CONFIG_IPC_MAJOR_4 .get_attribute = kpb_get_attribute, .bind = kpb_bind, .unbind = kpb_unbind, +#elif CONFIG_IPC_MAJOR_3 + .cmd = kpb_cmd, #endif /* CONFIG_IPC_MAJOR_4 */ }, }; diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 5bdfb68028dc..e30c6cbc51cb 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1252,129 +1252,6 @@ int module_adapter_copy(struct comp_dev *dev) return -EINVAL; } -static int module_adapter_get_set_params(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, - bool set) -{ - struct processing_module *mod = comp_get_drvdata(dev); - struct module_data *md = &mod->priv; - enum module_cfg_fragment_position pos; - uint32_t data_offset_size; - static uint32_t size; - - comp_dbg(dev, "module_adapter_set_params(): num_of_elem %d, elem remain %d msg_index %u", - cdata->num_elems, cdata->elems_remaining, cdata->msg_index); - - /* set the fragment position, data offset and config data size */ - if (!cdata->msg_index) { - size = cdata->num_elems + cdata->elems_remaining; - data_offset_size = size; - if (cdata->elems_remaining) - pos = MODULE_CFG_FRAGMENT_FIRST; - else - pos = MODULE_CFG_FRAGMENT_SINGLE; - } else { - data_offset_size = size - (cdata->num_elems + cdata->elems_remaining); - if (cdata->elems_remaining) - pos = MODULE_CFG_FRAGMENT_MIDDLE; - else - pos = MODULE_CFG_FRAGMENT_LAST; - } - - /* - * The type member in struct sof_abi_hdr is used for component's specific blob type - * for IPC3, just like it is used for component's specific blob param_id for IPC4. - */ - if (set && md->ops->set_configuration) - return md->ops->set_configuration(mod, cdata->data[0].type, pos, data_offset_size, - (const uint8_t *)cdata, cdata->num_elems, - NULL, 0); - else if (!set && md->ops->get_configuration) - return md->ops->get_configuration(mod, pos, &data_offset_size, - (uint8_t *)cdata, cdata->num_elems); - - comp_warn(dev, "module_adapter_get_set_params(): no configuration op set for %d", - dev_comp_id(dev)); - return 0; -} - -static int module_adapter_ctrl_get_set_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, - bool set) -{ - int ret; - struct processing_module *mod = comp_get_drvdata(dev); - - comp_dbg(dev, "module_adapter_ctrl_set_data() start, state %d, cmd %d", - mod->priv.state, cdata->cmd); - - /* Check version from ABI header */ - if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { - comp_err(dev, "module_adapter_ctrl_set_data(): ABI mismatch!"); - return -EINVAL; - } - - switch (cdata->cmd) { - case SOF_CTRL_CMD_ENUM: - comp_err(dev, "module_adapter_ctrl_set_data(): set enum is not implemented"); - ret = -EIO; - break; - case SOF_CTRL_CMD_BINARY: - ret = module_adapter_get_set_params(dev, cdata, set); - break; - default: - comp_err(dev, "module_adapter_ctrl_set_data error: unknown set data command"); - ret = -EINVAL; - break; - } - - return ret; -} - -/* Used to pass standard and bespoke commands (with data) to component */ -int module_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) -{ - struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4); - struct processing_module *mod = comp_get_drvdata(dev); - struct module_data *md = &mod->priv; - int ret = 0; - - comp_dbg(dev, "module_adapter_cmd() %d start", cmd); - - switch (cmd) { - case COMP_CMD_SET_DATA: - ret = module_adapter_ctrl_get_set_data(dev, cdata, true); - break; - case COMP_CMD_GET_DATA: - ret = module_adapter_ctrl_get_set_data(dev, cdata, false); - break; - case COMP_CMD_SET_VALUE: - /* - * IPC3 does not use config_id, so pass 0 for config ID as it will be ignored - * anyway. Also, pass the 0 as the fragment size as it is not relevant for the - * SET_VALUE command. - */ - if (md->ops->set_configuration) - ret = md->ops->set_configuration(mod, 0, MODULE_CFG_FRAGMENT_SINGLE, 0, - (const uint8_t *)cdata, 0, NULL, 0); - break; - case COMP_CMD_GET_VALUE: - /* - * IPC3 does not use config_id, so pass 0 for config ID as it will be ignored - * anyway. Also, pass the 0 as the fragment size and data offset as they are not - * relevant for the GET_VALUE command. - */ - if (md->ops->get_configuration) - ret = md->ops->get_configuration(mod, 0, 0, (uint8_t *)cdata, 0); - break; - default: - comp_err(dev, "module_adapter_cmd() error: unknown command"); - ret = -EINVAL; - break; - } - - comp_dbg(dev, "module_adapter_cmd() done"); - return ret; -} - int module_adapter_trigger(struct comp_dev *dev, int cmd) { struct processing_module *mod = comp_get_drvdata(dev); diff --git a/src/audio/module_adapter/module_adapter_ipc3.c b/src/audio/module_adapter/module_adapter_ipc3.c index 4327d8ee920b..7c3a2f1afb29 100644 --- a/src/audio/module_adapter/module_adapter_ipc3.c +++ b/src/audio/module_adapter/module_adapter_ipc3.c @@ -165,3 +165,125 @@ int module_adapter_set_state(struct processing_module *mod, struct comp_dev *dev return comp_set_state(dev, cmd); } +static int module_adapter_get_set_params(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, + bool set) +{ + struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + enum module_cfg_fragment_position pos; + uint32_t data_offset_size; + static uint32_t size; + + comp_dbg(dev, "module_adapter_set_params(): num_of_elem %d, elem remain %d msg_index %u", + cdata->num_elems, cdata->elems_remaining, cdata->msg_index); + + /* set the fragment position, data offset and config data size */ + if (!cdata->msg_index) { + size = cdata->num_elems + cdata->elems_remaining; + data_offset_size = size; + if (cdata->elems_remaining) + pos = MODULE_CFG_FRAGMENT_FIRST; + else + pos = MODULE_CFG_FRAGMENT_SINGLE; + } else { + data_offset_size = size - (cdata->num_elems + cdata->elems_remaining); + if (cdata->elems_remaining) + pos = MODULE_CFG_FRAGMENT_MIDDLE; + else + pos = MODULE_CFG_FRAGMENT_LAST; + } + + /* + * The type member in struct sof_abi_hdr is used for component's specific blob type + * for IPC3, just like it is used for component's specific blob param_id for IPC4. + */ + if (set && md->ops->set_configuration) + return md->ops->set_configuration(mod, cdata->data[0].type, pos, data_offset_size, + (const uint8_t *)cdata, cdata->num_elems, + NULL, 0); + else if (!set && md->ops->get_configuration) + return md->ops->get_configuration(mod, pos, &data_offset_size, + (uint8_t *)cdata, cdata->num_elems); + + comp_warn(dev, "module_adapter_get_set_params(): no configuration op set for %d", + dev_comp_id(dev)); + return 0; +} + +static int module_adapter_ctrl_get_set_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, + bool set) +{ + int ret; + struct processing_module *mod = comp_get_drvdata(dev); + + comp_dbg(dev, "module_adapter_ctrl_set_data() start, state %d, cmd %d", + mod->priv.state, cdata->cmd); + + /* Check version from ABI header */ + if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { + comp_err(dev, "module_adapter_ctrl_set_data(): ABI mismatch!"); + return -EINVAL; + } + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_err(dev, "module_adapter_ctrl_set_data(): set enum is not implemented"); + ret = -EIO; + break; + case SOF_CTRL_CMD_BINARY: + ret = module_adapter_get_set_params(dev, cdata, set); + break; + default: + comp_err(dev, "module_adapter_ctrl_set_data error: unknown set data command"); + ret = -EINVAL; + break; + } + + return ret; +} + +/* Used to pass standard and bespoke commands (with data) to component */ +int module_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) +{ + struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4); + struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + int ret = 0; + + comp_dbg(dev, "module_adapter_cmd() %d start", cmd); + + switch (cmd) { + case COMP_CMD_SET_DATA: + ret = module_adapter_ctrl_get_set_data(dev, cdata, true); + break; + case COMP_CMD_GET_DATA: + ret = module_adapter_ctrl_get_set_data(dev, cdata, false); + break; + case COMP_CMD_SET_VALUE: + /* + * IPC3 does not use config_id, so pass 0 for config ID as it will be ignored + * anyway. Also, pass the 0 as the fragment size as it is not relevant for the + * SET_VALUE command. + */ + if (md->ops->set_configuration) + ret = md->ops->set_configuration(mod, 0, MODULE_CFG_FRAGMENT_SINGLE, 0, + (const uint8_t *)cdata, 0, NULL, 0); + break; + case COMP_CMD_GET_VALUE: + /* + * IPC3 does not use config_id, so pass 0 for config ID as it will be ignored + * anyway. Also, pass the 0 as the fragment size and data offset as they are not + * relevant for the GET_VALUE command. + */ + if (md->ops->get_configuration) + ret = md->ops->get_configuration(mod, 0, 0, (uint8_t *)cdata, 0); + break; + default: + comp_err(dev, "module_adapter_cmd() error: unknown command"); + ret = -EINVAL; + break; + } + + comp_dbg(dev, "module_adapter_cmd() done"); + return ret; +} diff --git a/src/audio/rtnr/rtnr.c b/src/audio/rtnr/rtnr.c index 7db70e4425ac..61b4a9f2fb89 100644 --- a/src/audio/rtnr/rtnr.c +++ b/src/audio/rtnr/rtnr.c @@ -549,6 +549,7 @@ static int rtnr_set_config_bytes(struct comp_dev *dev, return ret; } +#if CONFIG_IPC_MAJOR_3 static int rtnr_set_bin_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) { struct comp_data *cd = comp_get_drvdata(dev); @@ -707,6 +708,7 @@ static int rtnr_cmd(struct comp_dev *dev, int cmd, void *data, return ret; } +#endif static int rtnr_trigger(struct comp_dev *dev, int cmd) { @@ -910,7 +912,9 @@ static const struct comp_driver comp_rtnr = { .create = rtnr_new, .free = rtnr_free, .params = rtnr_params, +#if CONFIG_IPC_MAJOR_3 .cmd = rtnr_cmd, +#endif .trigger = rtnr_trigger, .copy = rtnr_copy, .prepare = rtnr_prepare, diff --git a/src/audio/selector/selector.c b/src/audio/selector/selector.c index 55bf2af608d4..136fcac0232a 100644 --- a/src/audio/selector/selector.c +++ b/src/audio/selector/selector.c @@ -231,6 +231,7 @@ static int selector_params(struct comp_dev *dev, return 0; } +#if CONFIG_IPC_MAJOR_3 /** * \brief Sets selector control command. * \param[in,out] dev Selector base component device. @@ -339,6 +340,7 @@ static int selector_cmd(struct comp_dev *dev, int cmd, void *data, return ret; } +#endif /** * \brief Sets component state. @@ -525,7 +527,9 @@ static const struct comp_driver comp_selector = { .create = selector_new, .free = selector_free, .params = selector_params, +#if CONFIG_IPC_MAJOR_3 .cmd = selector_cmd, +#endif .trigger = selector_trigger, .copy = selector_copy, .prepare = selector_prepare, diff --git a/src/audio/smart_amp/smart_amp.c b/src/audio/smart_amp/smart_amp.c index 02b7ae2d5186..f6e336a5ed13 100644 --- a/src/audio/smart_amp/smart_amp.c +++ b/src/audio/smart_amp/smart_amp.c @@ -311,6 +311,7 @@ static int smart_amp_get_config(struct comp_dev *dev, return ret; } +#if CONFIG_IPC_MAJOR_3 static int smart_amp_ctrl_get_bin_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, int size) @@ -436,6 +437,7 @@ static int smart_amp_cmd(struct comp_dev *dev, int cmd, void *data, return -EINVAL; } } +#endif static void smart_amp_free(struct comp_dev *dev) { @@ -813,7 +815,9 @@ static const struct comp_driver comp_smart_amp = { .free = smart_amp_free, .params = smart_amp_params, .prepare = smart_amp_prepare, +#if CONFIG_IPC_MAJOR_3 .cmd = smart_amp_cmd, +#endif .trigger = smart_amp_trigger, .copy = smart_amp_copy, .reset = smart_amp_reset, diff --git a/src/audio/tone.c b/src/audio/tone.c index c669698bd13e..3ef1637f736b 100644 --- a/src/audio/tone.c +++ b/src/audio/tone.c @@ -453,6 +453,7 @@ static int tone_params(struct comp_dev *dev, return 0; } +#if CONFIG_IPC_MAJOR_3 static int tone_cmd_get_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, int max_size) { @@ -615,6 +616,7 @@ static int tone_cmd(struct comp_dev *dev, int cmd, void *data, return ret; } +#endif static int tone_trigger(struct comp_dev *dev, int cmd) { @@ -717,7 +719,9 @@ static const struct comp_driver comp_tone = { .create = tone_new, .free = tone_free, .params = tone_params, +#if CONFIG_IPC_MAJOR_3 .cmd = tone_cmd, +#endif .trigger = tone_trigger, .copy = tone_copy, .prepare = tone_prepare, diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 59214f3d2ee9..3896d2f55065 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -338,6 +338,7 @@ struct comp_ops { int (*dai_config)(struct dai_data *dd, struct comp_dev *dev, struct ipc_config_dai *dai_config, const void *dai_spec_config); +#if CONFIG_IPC_MAJOR_3 /** * Used to pass standard and bespoke commands (with optional data). * @param dev Component device. @@ -348,6 +349,7 @@ struct comp_ops { */ int (*cmd)(struct comp_dev *dev, int cmd, void *data, int max_data_size); +#endif /** * Trigger, atomic - used to start/stop/pause stream operations. diff --git a/src/include/sof/audio/component_ext.h b/src/include/sof/audio/component_ext.h index 208be66b1f8d..a3d04843b3f9 100644 --- a/src/include/sof/audio/component_ext.h +++ b/src/include/sof/audio/component_ext.h @@ -111,6 +111,7 @@ static inline int comp_dai_get_hw_params(struct comp_dev *dev, return -EINVAL; } +#if CONFIG_IPC_MAJOR_3 /** See comp_ops::cmd */ static inline int comp_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) @@ -132,6 +133,7 @@ static inline int comp_cmd(struct comp_dev *dev, int cmd, void *data, return -EINVAL; } +#endif /** * Runs comp_ops::trigger on the core the target component is assigned to. diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 10cbfa61acf9..1ab2485fe348 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -21,10 +21,6 @@ #include #include "module_interface.h" -#if CONFIG_INTEL_MODULES -#include "modules.h" -#endif - /* * helpers to determine processing type * Needed till all the modules use PROCESSING_MODE_SINK_SOURCE @@ -49,6 +45,12 @@ (value)); \ } while (0) +#if CONFIG_IPC_MAJOR_4 +#define IPC_MOD_CMD(v) +#elif CONFIG_IPC_MAJOR_3 +#define IPC_MOD_CMD(v) .cmd = v, +#endif + #define DECLARE_MODULE_ADAPTER(adapter, uuid, tr) \ static struct comp_dev *module_##adapter##_shim_new(const struct comp_driver *drv, \ const struct comp_ipc_config *config, \ @@ -66,7 +68,7 @@ static const struct comp_driver comp_##adapter##_module = { \ .prepare = module_adapter_prepare, \ .params = module_adapter_params, \ .copy = module_adapter_copy, \ - .cmd = module_adapter_cmd, \ + IPC_MOD_CMD(module_adapter_cmd) \ .trigger = module_adapter_trigger, \ .reset = module_adapter_reset, \ .free = module_adapter_free, \ diff --git a/src/include/sof/audio/module_adapter/module/modules.h b/src/include/sof/audio/module_adapter/module/modules.h index 07d099d4fdb9..ae514bcbf09e 100644 --- a/src/include/sof/audio/module_adapter/module/modules.h +++ b/src/include/sof/audio/module_adapter/module/modules.h @@ -8,6 +8,7 @@ #ifndef __SOF_AUDIO_MODULES__ #define __SOF_AUDIO_MODULES__ +#include #include /* Intel module adapter is an extension to SOF module adapter component that allows to integrate @@ -44,22 +45,27 @@ struct comp_dev *modules_shim_new(const struct comp_driver *drv, const struct comp_ipc_config *config, const void *spec); -#define DECLARE_DYNAMIC_MODULE_ADAPTER(comp_dynamic_module, mtype, uuid, tr) \ -do { \ - (comp_dynamic_module)->type = mtype; \ - (comp_dynamic_module)->uid = SOF_RT_UUID(uuid); \ - (comp_dynamic_module)->tctx = &(tr); \ - (comp_dynamic_module)->ops.create = modules_shim_new; \ - (comp_dynamic_module)->ops.prepare = module_adapter_prepare; \ - (comp_dynamic_module)->ops.params = module_adapter_params; \ - (comp_dynamic_module)->ops.copy = module_adapter_copy; \ - (comp_dynamic_module)->ops.cmd = module_adapter_cmd; \ - (comp_dynamic_module)->ops.trigger = module_adapter_trigger; \ - (comp_dynamic_module)->ops.reset = module_adapter_reset; \ - (comp_dynamic_module)->ops.free = module_adapter_free; \ - (comp_dynamic_module)->ops.set_large_config = module_set_large_config;\ - (comp_dynamic_module)->ops.get_large_config = module_get_large_config;\ - (comp_dynamic_module)->ops.get_attribute = module_adapter_get_attribute; \ -} while (0) +static inline void declare_dynamic_module_adapter(struct comp_driver *drv, + enum sof_comp_type mtype, + const struct sof_uuid *uuid, + struct tr_ctx *tr) +{ + drv->type = mtype; + drv->uid = uuid; + drv->tctx = tr; + drv->ops.create = modules_shim_new; + drv->ops.prepare = module_adapter_prepare; + drv->ops.params = module_adapter_params; + drv->ops.copy = module_adapter_copy; +#if CONFIG_IPC_MAJOR_3 + drv->ops.cmd = module_adapter_cmd; +#endif + drv->ops.trigger = module_adapter_trigger; + drv->ops.reset = module_adapter_reset; + drv->ops.free = module_adapter_free; + drv->ops.set_large_config = module_set_large_config; + drv->ops.get_large_config = module_get_large_config; + drv->ops.get_attribute = module_adapter_get_attribute; +} #endif /* __SOF_AUDIO_MODULES__ */ diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index b8f3644cf648..8bbef25e1415 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -389,7 +390,7 @@ int lib_manager_register_module(struct sof_man_fw_desc *desc, int module_id) mod = (struct sof_man_module *)((uint8_t *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); struct sof_uuid *uid = (struct sof_uuid *)&mod->uuid[0]; - DECLARE_DYNAMIC_MODULE_ADAPTER(drv, SOF_COMP_MODULE_ADAPTER, *uid, lib_manager_tr); + declare_dynamic_module_adapter(drv, SOF_COMP_MODULE_ADAPTER, uid, &lib_manager_tr); new_drv_info->drv = drv; From ac750edf05c298576bc5e0aa8de120fe89f2db3f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 27 Nov 2023 16:52:35 +0100 Subject: [PATCH 46/48] volume: remove superfluous cache invalidation IPC configuration data caches are already invalidated in ipc4_set_large_config_module_instance(), no need to imvalidate them additionally in the volume driver. Signed-off-by: Guennadi Liakhovetski --- src/audio/volume/volume_ipc4.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/audio/volume/volume_ipc4.c b/src/audio/volume/volume_ipc4.c index 9a9951169ce3..b47a3f8410b3 100644 --- a/src/audio/volume/volume_ipc4.c +++ b/src/audio/volume/volume_ipc4.c @@ -307,8 +307,6 @@ int volume_set_config(struct processing_module *mod, uint32_t config_id, comp_dbg(dev, "volume_set_config()"); - dcache_invalidate_region((__sparse_force void __sparse_cache *)fragment, fragment_size); - ret = module_set_configuration(mod, config_id, pos, data_offset_size, fragment, fragment_size, response, response_size); if (ret < 0) From 50c224a2c7ee38af1437adbae999517d366b6632 Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Thu, 30 Nov 2023 20:56:56 +0000 Subject: [PATCH 47/48] tools/plugin/README.md: add -GNinja. Remove stale -DPLUGIN_IPC4 Add instructions to build sof_ep and parser_ep first to avoid dependency issue and race condition. Signed-off-by: Marc Herbert --- tools/plugin/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/plugin/README.md b/tools/plugin/README.md index 0d4822388e70..1a9cac32746d 100644 --- a/tools/plugin/README.md +++ b/tools/plugin/README.md @@ -25,9 +25,11 @@ IPC3 is not functional and not supported ``` cd sof -mkdir build_plugin -cd build_plugin -cmake ../tools/plugin -DPLUGIN_IPC4=ON +cmake -GNinja -B build-plugin/ -S tools/plugin/ +# Build external projects first to avoid build race condition +# Dropping -GNinja is another (very slow) option. +cmake --build build-plugin/ -- sof_ep parser_ep +cmake --build build-plugin/ ``` then (use default ALSA prefix atm) From fb229b9cc1282779cbb289fbb0c2331f6fc893c0 Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Thu, 30 Nov 2023 20:58:35 +0000 Subject: [PATCH 48/48] .github/tools.tml: add build of SOF ALSA plugin Add new GitHub workflow that builds SOF ALSA plugin Signed-off-by: Marc Herbert --- .github/workflows/tools.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index 670d67ad9627..c0f72ecf1ba7 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -27,3 +27,29 @@ jobs: VERBOSE=1 NO_PROCESSORS=1 USE_XARGS=no CMAKE_BUILD_TYPE=Release ./scripts/docker-run.sh ./scripts/build-tools.sh + + + SOF-alsa-plugin: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: {filter: 'tree:0'} + + - name: apt install + run: sudo apt-get update; + sudo apt-get -y install ninja-build libasound2-dev + + # One space character is enough to detect most quoting issues + - name: configure + run: cmake -B 'build plugin' -S tools/plugin + -GNinja -Wdev -Werror=dev --warn-uninitialized + + # Retry with -j1 in case of error because parallel builds drown error + # messages. + - name: build ExternalProjects first to avoid build race condition + run: cmake --build 'build plugin' -- sof_ep parser_ep || + cmake --build 'build plugin' -- sof_ep parser_ep -j1 + + - name: Remaining build steps + run: cmake --build 'build plugin' || + cmake --build 'build plugin' -j1